tiangolo/fastapi · error · RuntimeError
New version {version} must be greater than current version {
Error message
New version {version} must be greater than current version {current_version} What it means
Raised by update_version_file() in scripts/prepare_release.py:56 when the requested new version is not strictly greater than the current version (parse_version(version) <= parse_version(current_version) at scripts/prepare_release.py:55). Releases must move forward; equal or lower versions are rejected to prevent regressions in published artifacts and PyPI.
Source
Thrown at scripts/prepare_release.py:56
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):
raise RuntimeError(
f"New version {version} must be greater than current version {current_version}"
)
return VERSION_PATTERN.sub(f'__version__ = "{version}"', content, count=1)
def update_release_notes(
content: str, version: str, release_date: date, release_notes_file: Path
) -> str:
if not content.startswith(RELEASE_NOTES_HEADER):
raise RuntimeError(
f"{release_notes_file} must start with {RELEASE_NOTES_HEADER!r}"
)
if re.search(rf"^## {re.escape(version)}(?: \([^)]+\))?$", content, re.M):
raise RuntimeError(f"Release notes already contain a section for {version}")
latest_header = f"{RELEASE_NOTES_HEADER}{LATEST_CHANGES_HEADER}\n"
if not content.startswith(latest_header):
raise RuntimeError(f"{release_notes_file} must start with {latest_header!r}")View on GitHub (pinned to 3e8d1526d8)
Solutions
- Check the current version: python scripts/prepare_release.py current-version --version-file <path>.
- Use a larger bump type (minor instead of patch) if the file is already ahead.
- Reset the version file to the last released version if it was bumped prematurely.
Example fix
# before — version file already at 1.2.3, asking for patch bump -> 1.2.3 (not greater) __version__ = "1.2.3" # after — bump minor or reset first __version__ = "1.2.2" # then run: prepare minor
Defensive patterns
Strategy: validation
Validate before calling
def new_gt_current(new: str, current: str) -> bool:
def t(v):
a, b, c = v.split(".")
return (int(a), int(b), int(c))
return t(new) > t(current) Try / catch
try:
new_content = update_version_file(content, version, version_file)
except RuntimeError as e:
raise SystemExit(f"Refusing to downgrade: {e}") from e Prevention
- Run prepare from a clean version file at the last released version.
- Avoid concurrent release runs that both bump the same file.
- Check current-version before invoking prepare.
When it happens
Trigger: Calling prepare with a version bump that resolves to <= current, or directly calling update_version_file with a lower/equal version. Can happen if the version file was already bumped ahead of the requested bump.
Common situations: Someone manually bumped __version__ before running prepare, so the computed bump (e.g. patch) is not greater than the new current. Two concurrent release attempts race. A hotfix version was passed manually below the released version.
Related errors
- Invalid version: {version!r}. Expected format: X.Y.Z
- Expected exactly one __version__ assignment in {version_file
- 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/3fea09c99b7430ea.
Report an issue: GitHub.