pypa/pip · error · InvalidWheelFilename

Wheel has unexpected file name: expected {dist_verstr!r}, go

Error message

Wheel has unexpected file name: expected {dist_verstr!r}, got {w.version!r}

What it means

Raised by `_verify_one` after building a wheel: the version recorded in the wheel filename (`w.version`) must match the version reported by the wheel's metadata (`dist.version`) after canonicalization. A mismatch indicates the wheel filename version and the `METADATA` Version field disagree — a sign of a broken build, stale egg-info, or a backend that emits inconsistent version strings.

Source

Thrown at src/pip/_internal/wheel_builder.py:103

    if cache_available and _should_cache(req):
        cache_dir = wheel_cache.get_path_for_link(req.link)
    else:
        cache_dir = wheel_cache.get_ephem_path_for_link(req.link)
    return cache_dir


def _verify_one(req: InstallRequirement, wheel_path: str) -> None:
    canonical_name = canonicalize_name(req.name or "")
    w = Wheel(os.path.basename(wheel_path))
    if w.name != canonical_name:
        raise InvalidWheelFilename(
            f"Wheel has unexpected file name: expected {canonical_name!r}, "
            f"got {w.name!r}",
        )
    dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name)
    dist_verstr = str(dist.version)
    if canonicalize_version(dist_verstr) != canonicalize_version(w.version):
        raise InvalidWheelFilename(
            f"Wheel has unexpected file name: expected {dist_verstr!r}, "
            f"got {w.version!r}",
        )
    metadata_version_value = dist.metadata_version
    if metadata_version_value is None:
        raise UnsupportedWheel("Missing Metadata-Version")
    try:
        metadata_version = Version(metadata_version_value)
    except InvalidVersion:
        msg = f"Invalid Metadata-Version: {metadata_version_value}"
        raise UnsupportedWheel(msg)
    if metadata_version >= Version("1.2") and not isinstance(dist.version, Version):
        raise UnsupportedWheel(
            f"Metadata 1.2 mandates PEP 440 version, but {dist_verstr!r} is not"
        )


def _build_one(

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Clean all build artefacts: `rm -rf build/ dist/ *.egg-info src/*.egg-info` and rebuild.
  2. Ensure version computation is deterministic — for dynamic versioning (setuptools_scm) confirm the same version is resolved at sdist and wheel stages.
  3. Inspect `dist/*.whl`'s `*.dist-info/METADATA` `Version:` line vs. the wheel filename to confirm the discrepancy source.
  4. If you hand-renamed the .whl file, restore the original filename.

Example fix

# before (stale egg-info forces old version into filename)
$ pip wheel .
-> InvalidWheelFilename: expected '1.0.0', got '0.9.0'

# after
$ rm -rf build/ dist/ src/mypkg.egg-info
$ pip wheel .
Defensive patterns

Strategy: validation

Validate before calling

from pip._internal.utils.wheel import Wheel
from pip._internal.utils.misc import canonicalize_version
from pip._internal.metadata import get_wheel_distribution
from pip._internal.models.direct_url import FilesystemWheel
import os

def verify_wheel_version(wheel_path: str) -> None:
    w = Wheel(os.path.basename(wheel_path))
    dist = get_wheel_distribution(FilesystemWheel(wheel_path), w.name)
    if canonicalize_version(str(dist.version)) != canonicalize_version(w.version):
        raise ValueError(f"Filename version {w.version!r} != metadata {dist.version!r}")

Type guard

null

Try / catch

from pip._internal.exceptions import InvalidWheelFilename
try:
    _verify_one(req, wheel_path)
except InvalidWheelFilename as e:
    # version mismatch -> clean stale egg-info and rebuild
    ...

Prevention

When it happens

Trigger: In `_verify_one`, after `dist = get_wheel_distribution(...)`, `canonicalize_version(dist_verstr) != canonicalize_version(w.version)`. Happens when the filename was generated with one version (e.g. from `setup.py sdist` cache) but `METADATA` reports another.

Common situations: Stale `*.egg-info` directory left from an older version causing the filename to use the old version while metadata uses the new; dynamic versioning (setuptools_scm) computed differently across build stages; a hand-edited wheel filename; partial build artefacts from a previous release.

Related errors


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