tiangolo/fastapi · error · RuntimeError
Expected exactly one __version__ assignment in {version_file
Error message
Expected exactly one __version__ assignment in {version_file}, found {len(matches)} What it means
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.
Source
Thrown at scripts/prepare_release.py:37
"""
LATEST_CHANGES_HEADER = "## Latest Changes"
BumpType = Literal["major", "minor", "patch"]
app = typer.Typer()
def parse_version(version: str) -> tuple[int, int, int]:
match = re.fullmatch(r"\d+\.\d+\.\d+", version)
if not match:
raise ValueError(f"Invalid version: {version!r}. Expected format: X.Y.Z")
major, minor, patch = version.split(".")
return int(major), int(minor), int(patch)
def get_current_version(content: str, version_file: Path) -> str:
matches = list(VERSION_PATTERN.finditer(content))
if len(matches) != 1:
raise RuntimeError(
f"Expected exactly one __version__ assignment in {version_file}, "
f"found {len(matches)}"
)
return matches[0].group(1)
def bump_version(version: str, bump: BumpType) -> str:
major, minor, patch = parse_version(version)
if bump == "major":
return f"{major + 1}.0.0"
if bump == "minor":
return f"{major}.{minor + 1}.0"
return f"{major}.{minor}.{patch + 1}"
def update_version_file(content: str, version: str, version_file: Path) -> str:
current_version = get_current_version(content, version_file)
if parse_version(version) <= parse_version(current_version):View on GitHub (pinned to 3e8d1526d8)
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).
Example fix
# before (two assignments) __version__ = "0.1.0" __version__ = "0.2.0" # after (exactly one) __version__ = "0.2.0"
Defensive patterns
Strategy: validation
Validate before calling
import re
from pathlib import Path
VERSION_PATTERN = re.compile(r'(?m)^__version__ = "(\d+\.\d+\.\d+)"$')
def has_single_version(path: Path) -> bool:
return len(VERSION_PATTERN.findall(path.read_text())) == 1 Try / catch
try:
current = get_current_version(content, version_file)
except RuntimeError as e:
raise SystemExit(f"Version file is ambiguous: {e}") from e Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Invalid version: {version!r}. Expected format: X.Y.Z
- New version {version} must be greater than current version {
- Release notes already contain a section for {version}
- {release_notes_file} must start with {RELEASE_NOTES_HEADER!r
- {release_notes_file} must start with {latest_header!r}
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/158618d7ad2f476f.
Report an issue: GitHub.