vectordotdev/vector · error
`## Summary` must not be empty
Error message
`## Summary` must not be empty
What it means
`parse_breaking_sections` extracts the text between the `## Summary` and `## Migration` headings, trims it, and bails with "`## Summary` must not be empty" if nothing remains. Every breaking change must carry an actual summary, since it is rendered into the release notes.
Solutions
- Write a one-to-few-sentence description under `## Summary` describing the breaking change.
- Re-run the changelog validation after filling it in.
Example fix
// before # My change ## Summary ## Migration Steps. // after # My change ## Summary The `foo` option was renamed to `bar`. ## Migration Steps.
Defensive patterns
Strategy: validation
Validate before calling
let summary = text
.split("## Summary").nth(1)
.and_then(|rest| rest.split("## Migration").next())
.unwrap_or("")
.trim();
if summary.is_empty() {
eprintln!("'## Summary' section must not be empty");
} Try / catch
if let Err(e) = parse_breaking_sections(text) {
eprintln!("fill in sections: {e}");
} Prevention
- Fill in both template sections before committing the fragment.
- Do not commit placeholder fragments with empty bodies.
- Run the changelog validation command as a pre-commit habit.
When it happens
Trigger: Parsing a breaking fragment where the `## Summary` heading is present but has no body content before the `## Migration` heading (or only whitespace).
Common situations: Creating the fragment from the template and filling in Migration but not Summary; deleting Summary text during edits; an automated tooling bug that strips the section body.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- content between the title and `## Summary` is not allowed —…
- exactly one `## Migration` section is required
- exactly one `## Summary` section is required
- H1 title must not be empty
- invalid breaking fragment
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/cec36750eec561dc.
Report an issue: GitHub.
Appendix: source
Thrown at vdev/src/commands/changelog/mod.rs:170
{
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("")
.trim()
.to_string();
let migration = after_title
.get(m_pos + MIGRATION_MARKER.len()..)
.unwrap_or("")
.trim()
.to_string();
if summary.is_empty() {
bail!("`## Summary` must not be empty");
}
Ok(BreakingSections {
title,
anchor: anchor.map(str::to_string),
summary,
migration,
})
}
/// Split `"Title Text {#anchor}"` into `("Title Text", Some("anchor"))`.
/// The `{#anchor}` suffix is a `Hugo`-style attribute list; `CommonMark` treats it as
/// plain text so we peel it off here.
pub(crate) fn split_title_and_anchor(line: &str) -> (&str, Option<&str>) {
let trimmed = line.trim_end();
if let Some(prefix) = trimmed.strip_suffix('}')
&& let Some(open) = prefix.rfind("{#")
{View on GitHub (pinned to bdb87aeaa4)