{"record":{"id":"85c19699055270b1","repo":"jenkinsci/jenkins","slug":"failed-to-parse-changelog","errorCode":null,"errorMessage":"Failed to parse changelog","messagePattern":"Failed to parse changelog","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/model/AbstractBuild.java","lineNumber":666,"sourceCode":"                    if (project.checkout(build, launcher, listener, changeLogFile)) {\n                        // check out succeeded\n                        SCM scm = project.getScm();\n                        for (SCMListener l : SCMListener.all()) {\n                            try {\n                                l.onCheckout(build, scm, build.getWorkspace(), listener, changeLogFile, build.getAction(SCMRevisionState.class));\n                            } catch (Exception e) {\n                                throw new IOException(e);\n                            }\n                        }\n\n                        build.scm = scm.createChangeLogParser();\n                        build.changeSet = new WeakReference<>(build.calcChangeSet());\n\n                        for (SCMListener l : SCMListener.all())\n                            try {\n                                l.onChangeLogParsed(build, listener, build.getChangeSet());\n                            } catch (Exception e) {\n                                throw new IOException(\"Failed to parse changelog\", e);\n                            }\n\n                        // Get a chance to do something after checkout and changelog is done\n                        scm.postCheckout(build, launcher, build.getWorkspace(), listener);\n\n                        return;\n                    }\n                } catch (AbortException e) {\n                    listener.error(e.getMessage());\n                } catch (ClosedByInterruptException | InterruptedIOException e) {\n                    throw (InterruptedException) new InterruptedException().initCause(e);\n                } catch (IOException e) {\n                    // checkout error not yet reported\n                    Functions.printStackTrace(e, listener.getLogger());\n                }\n\n                if (retryCount == 0)   // all attempts failed\n                    throw new RunnerAbortedException();","sourceCodeStart":648,"sourceCodeEnd":684,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/model/AbstractBuild.java#L648-L684","documentation":"Thrown during the checkout/run phase when an SCMListener.onChangeLogParsed(build, listener, changeSet) throws an Exception. The exception is wrapped in an IOException with the message 'Failed to parse changelog'. This is not a parse error in the changelog file itself per se, but a failure in a registered SCMListener processing the parsed change set.","triggerScenarios":"During build checkout, after build.calcChangeSet() produces the change set, the loop over SCMListener.all() calls onChangeLogParsed on each listener; any listener throwing causes this IOException.","commonSituations":"A plugin providing an SCMListener (e.g. a notification or git-trait plugin) throws due to an unexpected change-set shape, a null field, a network call to an external system, or a serialization issue; a version mismatch between the SCM plugin and a listener plugin after an upgrade.","solutions":["Examine the wrapped cause (IOException.getCause()) to identify which SCMListener failed and why","Update or patch the plugin that registered the failing SCMListener","Temporarily disable the offending listener plugin to confirm it is the culprit","If you author an SCMListener, wrap onChangeLogParsed logic in try/catch and log rather than propagate"],"exampleFix":"// before: SCMListener throws, killing the build\n@Override\npublic void onChangeLogParsed(Run build, BuildListener listener, ChangeLogSet<?> changeSet) {\n    notifyExternal(build);\n}\n// after: guard listener logic\n@Override\npublic void onChangeLogParsed(Run build, BuildListener listener, ChangeLogSet<?> changeSet) {\n    try {\n        notifyExternal(build);\n    } catch (Exception e) {\n        listener.getLogger().println(\"SCM listener warning: \" + e.getMessage());\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    // checkout / changelog parsing phase\n} catch (IOException e) {\n    if (\"Failed to parse changelog\".equals(e.getMessage()) && e.getCause() != null) {\n        // the cause identifies the failing SCMListener; handle accordingly\n    }\n    throw e;\n}","preventionTips":["If you implement SCMListener.onChangeLogParsed, catch your own exceptions and log, do not propagate","Keep SCM-related plugins at compatible versions after upgrades","Inspect the wrapped cause to pinpoint the failing listener plugin"],"tags":["build","scm","changelog","scmlistener","checkout","plugin"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}