{"record":{"id":"158618d7ad2f476f","repo":"tiangolo/fastapi","slug":"expected-exactly-one-version-assignment-in-ve","errorCode":null,"errorMessage":"Expected exactly one __version__ assignment in {version_file}, found {len(matches)}","messagePattern":"Expected exactly one __version__ assignment in (.+?), found (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scripts/prepare_release.py","lineNumber":37,"sourceCode":"\"\"\"\nLATEST_CHANGES_HEADER = \"## Latest Changes\"\nBumpType = Literal[\"major\", \"minor\", \"patch\"]\n\napp = typer.Typer()\n\n\ndef parse_version(version: str) -> tuple[int, int, int]:\n    match = re.fullmatch(r\"\\d+\\.\\d+\\.\\d+\", version)\n    if not match:\n        raise ValueError(f\"Invalid version: {version!r}. Expected format: X.Y.Z\")\n    major, minor, patch = version.split(\".\")\n    return int(major), int(minor), int(patch)\n\n\ndef get_current_version(content: str, version_file: Path) -> str:\n    matches = list(VERSION_PATTERN.finditer(content))\n    if len(matches) != 1:\n        raise RuntimeError(\n            f\"Expected exactly one __version__ assignment in {version_file}, \"\n            f\"found {len(matches)}\"\n        )\n    return matches[0].group(1)\n\n\ndef bump_version(version: str, bump: BumpType) -> str:\n    major, minor, patch = parse_version(version)\n    if bump == \"major\":\n        return f\"{major + 1}.0.0\"\n    if bump == \"minor\":\n        return f\"{major}.{minor + 1}.0\"\n    return f\"{major}.{minor}.{patch + 1}\"\n\n\ndef update_version_file(content: str, version: str, version_file: Path) -> str:\n    current_version = get_current_version(content, version_file)\n    if parse_version(version) <= parse_version(current_version):","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/scripts/prepare_release.py#L19-L55","documentation":"Raised by get_current_version() in scripts/prepare_release.py:37 when VERSION_PATTERN (a multiline regex for exactly `__version__ = \"X.Y.Z\"`) does not match exactly once in the version file. The release tool needs an unambiguous single source of truth for the current version; zero matches means it cannot find it, two or more means it cannot decide which is authoritative.","triggerScenarios":"Calling prepare / current-version / release-notes. VERSION_PATTERN.finditer returns 0 (no __version__ assignment, or one with different quoting/spacing) or >1 (multiple assignments, e.g. a module-level constant and a duplicated line).","commonSituations":"The version file was refactored and __version__ moved into __init__.py elsewhere. Quoting style changed from double to single quotes. A second __version__ assignment was added conditionally. The path points at the wrong file.","solutions":["Ensure the version file contains exactly one line of the form `__version__ = \"X.Y.Z\"` with double quotes.","Remove any duplicate __version__ assignments.","Point --version-file at the file that is the canonical version source (e.g. fastapi/__init__.py)."],"exampleFix":"# before (two assignments)\n__version__ = \"0.1.0\"\n__version__ = \"0.2.0\"\n# after (exactly one)\n__version__ = \"0.2.0\"","handlingStrategy":"validation","validationCode":"import re\nfrom pathlib import Path\n\nVERSION_PATTERN = re.compile(r'(?m)^__version__ = \"(\\d+\\.\\d+\\.\\d+)\"$')\n\ndef has_single_version(path: Path) -> bool:\n    return len(VERSION_PATTERN.findall(path.read_text())) == 1","typeGuard":null,"tryCatchPattern":"try:\n    current = get_current_version(content, version_file)\nexcept RuntimeError as e:\n    raise SystemExit(f\"Version file is ambiguous: {e}\") from e","preventionTips":["Maintain exactly one `__version__ = \"X.Y.Z\"` line with double quotes in the canonical file.","Lint for duplicate __version__ assignments in pre-commit.","Point --version-file at the package __init__.py consistently."],"tags":["release","versioning","validation"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}