{"record":{"id":"501988be351de24f","repo":"tiangolo/fastapi","slug":"release-notes-section-for-version-in-release-no","errorCode":null,"errorMessage":"Release notes section for {version} in {release_notes_file} is empty","messagePattern":"Release notes section for (.+?) in (.+?) is empty","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scripts/prepare_release.py","lineNumber":96,"sourceCode":"        latest_header,\n        f\"{RELEASE_NOTES_HEADER}{LATEST_CHANGES_HEADER}\\n\\n{release_header}\\n\",\n        1,\n    )\n\n\ndef get_release_notes_body(content: str, version: str, release_notes_file: Path) -> str:\n    version_heading = re.compile(rf\"(?m)^## {re.escape(version)}(?: \\([^)]+\\))?$\")\n    match = version_heading.search(content)\n    if not match:\n        raise RuntimeError(\n            f\"Could not find release notes section for {version} in {release_notes_file}\"\n        )\n\n    next_match = VERSION_HEADING_PATTERN.search(content, match.end())\n    end = next_match.start() if next_match else len(content)\n    body = content[match.end() : end].strip()\n    if not body:\n        raise RuntimeError(\n            f\"Release notes section for {version} in {release_notes_file} is empty\"\n        )\n    return f\"{body}\\n\"\n\n\n@app.command()\ndef prepare(\n    bump: Annotated[\n        BumpType,\n        typer.Argument(\n            envvar=\"PREPARE_RELEASE_BUMP\",\n            help=\"The release bump to make: major, minor, or patch.\",\n        ),\n    ],\n    version_file: Annotated[\n        Path,\n        typer.Option(\n            envvar=\"PREPARE_RELEASE_VERSION_FILE\",","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/scripts/prepare_release.py#L78-L114","documentation":"Raised by get_release_notes_body() in scripts/prepare_release.py:96 when the version section heading exists but its body (text up to the next '## ' heading, stripped) is empty (scripts/prepare_release.py:94-95). The release-notes command is meant to output the changelog body for tooling, so an empty body is treated as an error rather than emitting nothing.","triggerScenarios":"Running `release-notes` for a version whose '## X.Y.Z' heading was added but contains no bullet points (e.g. a placeholder section), or where all content between headings is whitespace.","commonSituations":"prepare created the heading but no PR descriptions were added under it. A maintainer added the heading as a stub. Content was accidentally deleted leaving the heading orphaned.","solutions":["Populate the section with at least one changelog entry under the '## <version>' heading.","Remove the empty heading if the version is not being released.","Re-run release-notes once the section has content."],"exampleFix":"<!-- before -->\n## 1.2.3 (2026-01-01)\n\n## 1.2.2 (2025-12-01)\n<!-- after -->\n## 1.2.3 (2026-01-01)\n- Fixed login redirect\n\n## 1.2.2 (2025-12-01)","handlingStrategy":"validation","validationCode":"import re\nfrom pathlib import Path\n\ndef section_has_body(path: Path, version: str) -> bool:\n    text = path.read_text(encoding=\"utf-8\")\n    m = re.search(rf\"(?m)^## {re.escape(version)}(?: \\([^)]+\\))?$\", text)\n    if not m:\n        return False\n    nxt = re.search(r\"(?m)^## \", text[m.end():])\n    body = text[m.end(): m.end() + (nxt.start() if nxt else len(text) - m.end())].strip()\n    return bool(body)","typeGuard":null,"tryCatchPattern":"try:\n    body = get_release_notes_body(content, version, release_notes_file)\nexcept RuntimeError as e:\n    if \"is empty\" in str(e):\n        raise SystemExit(f\"Add changelog entries under ## {version}\") from e\n    raise","preventionTips":["Require at least one bullet under each version heading before tagging a release.","CI: fail if a released version's section body is empty.","Remove stub headings for versions you do not intend to release."],"tags":["release","docs","validation"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}