{"record":{"id":"694273f38dedfc90","repo":"vectordotdev/vector","slug":"summary-must-come-before-migration","errorCode":null,"errorMessage":"`## Summary` must come before `## Migration`","messagePattern":"`## Summary` must come before `## Migration`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vdev/src/commands/changelog/mod.rs","lineNumber":142,"sourceCode":"        .ok_or_else(|| anyhow::anyhow!(\"first line must be an H1 title (`# ...`)\"))?;\n    let (title_line, after_title) = title_body.split_once('\\n').unwrap_or((title_body, \"\"));\n    let (title_text, anchor) = split_title_and_anchor(title_line);\n    let title = title_text.to_string();\n    if title.is_empty() {\n        bail!(\"H1 title must not be empty\");\n    }\n\n    // 2) Exactly one `## Summary` and one `## Migration`, in that order.\n    if after_title.matches(SUMMARY_MARKER).count() != 1 {\n        bail!(\"exactly one `## Summary` section is required\");\n    }\n    if after_title.matches(MIGRATION_MARKER).count() != 1 {\n        bail!(\"exactly one `## Migration` section is required\");\n    }\n    let s_pos = after_title.find(SUMMARY_MARKER).unwrap();\n    let m_pos = after_title.find(MIGRATION_MARKER).unwrap();\n    if s_pos >= m_pos {\n        bail!(\"`## Summary` must come before `## Migration`\");\n    }\n\n    // Reject any prose between the H1 title and `## Summary`. Someone hand-migrating an\n    // old free-form breaking fragment could carry over the previous body here and it\n    // would silently disappear from both the release CUE and the upgrade guide.\n    // Everything before Summary must be whitespace (`\\n## Summary\\n` starts with the\n    // leading newline, so `s_pos` includes it).\n    if let Some(prefix) = after_title.get(..s_pos)\n        && !prefix.trim().is_empty()\n    {\n        bail!(\n            \"content between the title and `## Summary` is not allowed — move it into `## Summary` or `## Migration`.\"\n        );\n    }\n\n    let summary = after_title\n        .get(s_pos + SUMMARY_MARKER.len()..m_pos)\n        .unwrap_or(\"\")","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/vdev/src/commands/changelog/mod.rs#L124-L160","documentation":"`parse_breaking_sections` enforces section ordering: the position of `## Summary` in the text after the title must be strictly before the position of `## Migration`. If Summary appears at or after Migration, it bails with \"`## Summary` must come before `## Migration`\".","triggerScenarios":"Parsing a breaking fragment where the `## Migration` section is written before the `## Summary` section.","commonSituations":"Reordering sections manually while editing a fragment; copy-pasting a template's sections in the wrong order; merging fragments and concatenating headings out of order.","solutions":["Swap the two sections so `## Summary` comes first, followed by `## Migration`.","Re-run the vdev changelog validation to confirm the order is accepted."],"exampleFix":"// before\n# Title\n## Migration\nDo X.\n## Summary\nY changed.\n// after\n# Title\n## Summary\nY changed.\n## Migration\nDo X.","handlingStrategy":"validation","validationCode":"let after_title = &text[text.find('\\n').unwrap_or(0)..];\nlet s = after_title.find(\"## Summary\").unwrap_or(usize::MAX);\nlet m = after_title.find(\"## Migration\").unwrap_or(usize::MAX);\nif s >= m {\n    eprintln!(\"'## Summary' must appear before '## Migration'\");\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = parse_breaking_sections(text) {\n    eprintln!(\"reorder sections: {e}\");\n}","preventionTips":["Keep the template order: title, Summary, Migration.","Do not reorder sections when editing content.","Run the changelog check in CI/pre-push to catch ordering mistakes."],"tags":["changelog","validation","ordering"],"backgroundTag":"invalid-state-transition","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}