pypa/pip · error · PylockValidationError

Invalid wheel filename {wheel.filename!r}

Error message

Invalid wheel filename {wheel.filename!r}

What it means

Raised as PylockValidationError by Package._from_dict in packaging.pylock when parse_wheel_filename(wheel.filename) raises (e.g. InvalidWheelFilename). It wraps the underlying error and tags the context with 'wheels[{i}]' so the offending wheel is identifiable. The filename must match the PEP 427 wheel naming convention.

Source

Thrown at src/pip/_vendor/packaging/pylock.py:601

        )
        distributions = bool(package.sdist) + len(package.wheels or [])
        direct_urls = (
            bool(package.vcs) + bool(package.directory) + bool(package.archive)
        )
        if distributions > 0 and direct_urls > 0:
            raise PylockValidationError(
                "None of vcs, directory, archive must be set if sdist or wheels are set"
            )
        if distributions == 0 and direct_urls != 1:
            raise PylockValidationError(
                "Exactly one of vcs, directory, archive must be set "
                "if sdist and wheels are not set"
            )
        for i, wheel in enumerate(package.wheels or []):
            try:
                (name, version, _, _) = parse_wheel_filename(wheel.filename)
            except Exception as e:
                raise PylockValidationError(
                    f"Invalid wheel filename {wheel.filename!r}",
                    context=f"wheels[{i}]",
                ) from e
            if name != package.name:
                raise PylockValidationError(
                    f"Name in {wheel.filename!r} is not consistent with "
                    f"package name {package.name!r}",
                    context=f"wheels[{i}]",
                )
            if package.version and version != package.version:
                raise PylockValidationError(
                    f"Version in {wheel.filename!r} is not consistent with "
                    f"package version {str(package.version)!r}",
                    context=f"wheels[{i}]",
                )
        if package.sdist:
            try:
                name, version = parse_sdist_filename(package.sdist.filename)

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Set the wheel name/path/url to a valid PEP 427 filename: {distribution}-{version}-{python}-{abi}-{platform}.whl.
  2. Regenerate the lockfile so the resolver records correct wheel filenames.
  3. If setting path/url, ensure the basename is the wheel filename.
  4. Catch the error and report the bad filename and wheel index (context).

Example fix

# before
[[packages.wheels]]
name = \"foo-1.0\"
# after
[[packages.wheels]]
name = \"foo-1.0-py3-none-any.whl\"
Defensive patterns

Strategy: validation

Validate before calling

from packaging.utils import parse_wheel_filename

def is_valid_wheel_name(fname: str) -> bool:
    try:
        parse_wheel_filename(fname)
        return True
    except Exception:
        return False

Type guard

import re
from packaging.utils import parse_wheel_filename

def is_wheel_filename(s: str) -> bool:
    if not isinstance(s, str) or not s.endswith('.whl'):
        return False
    try:
        parse_wheel_filename(s)
        return True
    except Exception:
        return False

Try / catch

try:
    PylockFile.from_dict(data)
except PylockValidationError as e:
    if 'Invalid wheel filename' in str(e):
        repair_wheel_name(e.context)

Prevention

When it happens

Trigger: A wheel entry whose name/path/url resolves to a non-wheel filename like 'pkg-1.0.tar.gz', a malformed wheel name 'pkg.whl' (missing tags), or a name with invalid characters. Constructed via the wheel validation loop in Package._from_dict.

Common situations: Lockfile pointing a wheel entry at an sdist filename; truncated wheel name; tooling that recorded the project name instead of the wheel filename; cross-platform path separators breaking the filename extraction.

Related errors


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