pypa/pip · error · InvalidSdistFilename

Invalid sdist filename (invalid version): {filename!r}

Error message

Invalid sdist filename (invalid version): {filename!r}

What it means

Raised by `parse_sdist_filename` when the version segment (everything after the last dash in the stem) cannot be parsed as a PEP 440 version via `Version(version_part)`. The underlying `InvalidVersion` is caught and re-raised as `InvalidSdistFilename` with the cause chained (`from e`). Since PEP 440 versions contain no dashes, splitting on the last dash cleanly isolates the version string.

Source

Thrown at src/pip/_vendor/packaging/utils.py:292

        file_stem = filename[: -len(".zip")]
    else:
        raise InvalidSdistFilename(
            f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
            f" {filename!r}"
        )

    # We are requiring a PEP 440 version, which cannot contain dashes,
    # so we split on the last dash.
    name_part, sep, version_part = file_stem.rpartition("-")
    if not sep:
        raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}")

    name = canonicalize_name(name_part)

    try:
        version = Version(version_part)
    except InvalidVersion as e:
        raise InvalidSdistFilename(
            f"Invalid sdist filename (invalid version): {filename!r}"
        ) from e

    return (name, version)

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Normalize the project version to PEP 440 (drop leading `v`, use setuptools-scm's default normalization).
  2. Validate the version in isolation with `Version(v)` to see the exact reason, then fix.
  3. Rename the sdist to embed a valid version segment.
  4. Rebuild the sdist with a compliant backend.

Example fix

// before
parse_sdist_filename('foo-v1.0.tar.gz')  # 'v1.0' invalid -> raises

// after
parse_sdist_filename('foo-1.0.tar.gz')
Defensive patterns

Strategy: try-catch

Validate before calling

from pip._vendor.packaging.version import Version, InvalidVersion

def has_valid_sdist_version(filename: str) -> bool:
    if filename.endswith('.tar.gz'):
        stem = filename[:-7]
    elif filename.endswith('.zip'):
        stem = filename[:-4]
    else:
        return False
    name_part, sep, version_part = stem.rpartition('-')
    if not sep:
        return False
    try:
        Version(version_part)
        return True
    except InvalidVersion:
        return False

Try / catch

from pip._vendor.packaging.utils import parse_sdist_filename, InvalidSdistFilename

try:
    name, ver = parse_sdist_filename(filename)
except InvalidSdistFilename as e:
    if 'invalid version' in str(e):
        # normalize the project version to PEP 440, then rebuild/rename
        ...
    raise

Prevention

When it happens

Trigger: A version segment like `v1.0`, `1.0.beta`, `20240305`, or any non-PEP-440 string after the last dash; sdist built from a project with a git-describe or date-based version that wasn't normalized.

Common situations: Projects setting `version` from `git describe --tags` (e.g. `v1.0-3-gabc`) without normalization; leading `v` in versions; date-only version schemes that violate PEP 440; renamed sdists.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/f65982e3e6d8cf47.json. Report an issue: GitHub.