vectordotdev/vector · error
`## Summary` must come before `## Migration`
Error message
`## Summary` must come before `## Migration`
What it means
`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`".
Solutions
- Swap the two sections so `## Summary` comes first, followed by `## Migration`.
- Re-run the vdev changelog validation to confirm the order is accepted.
Example fix
// before # Title ## Migration Do X. ## Summary Y changed. // after # Title ## Summary Y changed. ## Migration Do X.
Defensive patterns
Strategy: validation
Validate before calling
let after_title = &text[text.find('\n').unwrap_or(0)..];
let s = after_title.find("## Summary").unwrap_or(usize::MAX);
let m = after_title.find("## Migration").unwrap_or(usize::MAX);
if s >= m {
eprintln!("'## Summary' must appear before '## Migration'");
} Try / catch
if let Err(e) = parse_breaking_sections(text) {
eprintln!("reorder sections: {e}");
} Prevention
- 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.
When it happens
Trigger: Parsing a breaking fragment where the `## Migration` section is written before the `## Summary` section.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- breaking fragment ' ' has an invalid anchor ' '. Add ` }`…
- content between the title and `## Summary` is not allowed —…
- Duplicate deprecation fragments for `what
- duplicate upgrade-guide anchor '#
- exactly one `## Migration` section is required
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/694273f38dedfc90.
Report an issue: GitHub.
Appendix: source
Thrown at vdev/src/commands/changelog/mod.rs:142
.ok_or_else(|| anyhow::anyhow!("first line must be an H1 title (`# ...`)"))?;
let (title_line, after_title) = title_body.split_once('\n').unwrap_or((title_body, ""));
let (title_text, anchor) = split_title_and_anchor(title_line);
let title = title_text.to_string();
if title.is_empty() {
bail!("H1 title must not be empty");
}
// 2) Exactly one `## Summary` and one `## Migration`, in that order.
if after_title.matches(SUMMARY_MARKER).count() != 1 {
bail!("exactly one `## Summary` section is required");
}
if after_title.matches(MIGRATION_MARKER).count() != 1 {
bail!("exactly one `## Migration` section is required");
}
let s_pos = after_title.find(SUMMARY_MARKER).unwrap();
let m_pos = after_title.find(MIGRATION_MARKER).unwrap();
if s_pos >= m_pos {
bail!("`## Summary` must come before `## Migration`");
}
// Reject any prose between the H1 title and `## Summary`. Someone hand-migrating an
// old free-form breaking fragment could carry over the previous body here and it
// would silently disappear from both the release CUE and the upgrade guide.
// Everything before Summary must be whitespace (`\n## Summary\n` starts with the
// leading newline, so `s_pos` includes it).
if let Some(prefix) = after_title.get(..s_pos)
&& !prefix.trim().is_empty()
{
bail!(
"content between the title and `## Summary` is not allowed — move it into `## Summary` or `## Migration`."
);
}
let summary = after_title
.get(s_pos + SUMMARY_MARKER.len()..m_pos)
.unwrap_or("")View on GitHub (pinned to bdb87aeaa4)