pypa/pip · error · InvalidWheelFilename

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

Error message

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

What it means

Raised by `parse_wheel_filename` when the version segment of the filename cannot be parsed as a PEP 440 version via `Version(parts[1])`. The parser catches the underlying `InvalidVersion` and re-raises it as `InvalidWheelFilename`, so the cause is attached via `from e`. Wheel filenames must carry a valid PEP 440 version in the second dash-separated position.

Source

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

    filename = filename[:-4]
    dashes = filename.count("-")
    if dashes not in (4, 5):
        raise InvalidWheelFilename(
            f"Invalid wheel filename (wrong number of parts): {filename!r}"
        )

    parts = filename.split("-", dashes - 2)
    name_part = parts[0]
    # See PEP 427 for the rules on escaping the project name.
    if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None:
        raise InvalidWheelFilename(f"Invalid project name: {filename!r}")
    name = canonicalize_name(name_part)

    try:
        version = Version(parts[1])
    except InvalidVersion as e:
        raise InvalidWheelFilename(
            f"Invalid wheel filename (invalid version): {filename!r}"
        ) from e

    if dashes == 5:
        build_part = parts[2]
        build_match = _build_tag_regex.match(build_part)
        if build_match is None:
            raise InvalidWheelFilename(
                f"Invalid build number: {build_part} in {filename!r}"
            )
        build = cast("BuildTag", (int(build_match.group(1)), build_match.group(2)))
    else:
        build = ()
    tag_str = parts[-1]
    try:
        tags = parse_tag(tag_str, validate_order=validate_order)
    except UnsortedTagsError:
        raise InvalidWheelFilename(

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Set the project version to a PEP 440-compliant string (`1.0`, `1.0a1`, `1.0.post1`, `1.0+local`).
  2. Strip a leading `v` from the version before build, or configure setuptools to do so.
  3. Use `Version(version_str)` directly to surface the precise `InvalidVersion` reason, then fix it.
  4. Re-fetch the wheel from the index if it was externally produced and malformed.

Example fix

// before
parse_wheel_filename('foo-v1.0-py3-none-any.whl')  # 'v1.0' not PEP 440

# after
parse_wheel_filename('foo-1.0-py3-none-any.whl')
Defensive patterns

Strategy: try-catch

Validate before calling

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

def has_valid_wheel_version(filename: str) -> bool:
    if not filename.endswith('.whl'):
        return False
    stem = filename[:-4]
    # version is the segment after the first dash in the split scheme
    parts = stem.split('-', stem.count('-') - 2)
    try:
        Version(parts[1])
        return True
    except InvalidVersion:
        return False

Try / catch

from pip._vendor.packaging.utils import parse_wheel_filename, InvalidWheelFilename

try:
    name, ver, build, tags = parse_wheel_filename(filename)
except InvalidWheelFilename as e:
    if 'invalid version' in str(e):
        # fix the project version to PEP 440, then rebuild
        ...
    raise

Prevention

When it happens

Trigger: A version segment like `1.0.0.0.0.0` (too many components is fine but unusual punctuation is not), `1.0.beta` (wrong pre-release separator), `v1.0` (leading 'v'), `1.0..2` (empty), or any non-PEP-440 string in the version slot.

Common situations: A wheel built from a project whose version was set to a non-PEP-440 string (git-describe output, a leading 'v', date schemes like `2024.03.05.rc1` with bad punctuation); renaming that corrupted the version; upstream packages with sloppy versions.

Related errors


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