{"record":{"id":"b8bba8209015a38e","repo":"vectordotdev/vector","slug":"commit-title-must-end-with-pr-number","errorCode":null,"errorMessage":"Commit title must end with `(#<PR number>)`","messagePattern":"Commit title must end with `\\(#<PR number>\\)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vdev/src/commands/release/generate_cue.rs","lineNumber":519,"sourceCode":"        }\n    }\n\n    match pull_request_metadata {\n        PullRequestMetadata::Optional => Ok(Vec::new()),\n        PullRequestMetadata::Required => {\n            bail!(\"Could not find latest addition commit {latest_addition} in the fragment history\")\n        }\n    }\n}\n\nfn parse_pull_request_number(commit_title: &str) -> Result<u64> {\n    let number = commit_title\n        .trim()\n        .strip_suffix(')')\n        .and_then(|title| title.rsplit_once(\"(#\"))\n        .map(|(_, number)| number)\n        .filter(|number| !number.is_empty() && number.bytes().all(|byte| byte.is_ascii_digit()))\n        .ok_or_else(|| anyhow!(\"Commit title must end with `(#<PR number>)`\"))?;\n\n    number\n        .parse()\n        .with_context(|| format!(\"Invalid PR number in commit title `{commit_title}`\"))\n}\n\n#[cfg(not(test))]\nfn ensure_full_git_history(repo_root: &Path) -> Result<()> {\n    let is_shallow = run_command(\"git\", &[\"rev-parse\", \"--is-shallow-repository\"], repo_root)?;\n    if is_shallow.trim() == \"true\" {\n        bail!(\n            \"Release generation requires full Git history to find the PRs that introduced changelog fragments.\"\n        );\n    }\n    Ok(())\n}\n\n#[cfg(test)]","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/vectordotdev/vector/blob/0d4ab78a4f0d9c9e5d03a50108a2ae4d2f4b2460/vdev/src/commands/release/generate_cue.rs#L501-L537","documentation":"The release tooling requires every commit title on a release branch to end with a PR reference in the form `(#<digits>)`, so PR metadata can be recovered from history. This error fires when a commit title does not match that pattern (no trailing '(#N)'), unless PullRequestMetadata::Optional is configured.","triggerScenarios":"parse_pull_request_history processes a commit whose title lacks a trailing `(#123)`; this propagates up from lookup_pull_requests during release CUE generation when pull request metadata is required.","commonSituations":"A maintainer squash-merged a PR with the '(#N)' suffix stripped by a custom merge-commit template; a direct push to the release branch bypassing PRs; a PR title manually edited to drop the number.","solutions":["Amend or rebase the offending commit so its title ends with `(#<PR number>)` (e.g. `git commit --amend -m \"fix: thing (#12345)\"`).","If PR metadata is intentionally absent for some commits, use the Optional PullRequestMetadata mode in the release command.","Identify the commit via the context line added by the error (\"Commit <sha>: `<title>`\") and fix it first, then re-run."],"exampleFix":"// before\ngit commit --amend -m \"fix: correct TLS handshake\"\n// after\ngit commit --amend -m \"fix: correct TLS handshake (#12345)\"","handlingStrategy":"validation","validationCode":"let title_ok = |t: &str| {\n    t.trim().strip_suffix(')')\n        .and_then(|t| t.rsplit_once(\"(#\"))\n        .map(|(_, n)| !n.is_empty() && n.bytes().all(|b| b.is_ascii_digit()))\n        .unwrap_or(false)\n};\n// check every commit title on the release branch before preparing a release","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always squash-merge with the default template that appends (#N)","Block direct pushes to release branches","Enable branch protection requiring PR merges so titles carry (#N)"],"tags":["rust","git","commit-convention"],"backgroundTag":"invalid-identifier-format","analyzedSha":"0d4ab78a4f0d9c9e5d03a50108a2ae4d2f4b2460","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}