pypa/pip · error · PylockValidationError

Cannot determine wheel filename

Error message

Cannot determine wheel filename

What it means

Raised by the PackageWheel.filename property in pylock.py:529-532 when none of 'name', path basename, or url basename yields a filename. Used by Package._from_dict (pylock.py:615) to run parse_wheel_filename (which checks name/version/tag consistency), and exposed publicly.

Solutions

  1. Set name = "pkg-1.0-py3-none-any.whl" explicitly, or
  2. Make the url/path end in the wheel filename (remove trailing slash).

Example fix

# before
[[packages.wheels]]
url = "https://example.com/"
hashes = { sha256 = "..." }
# after
[[packages.wheels]]
name = "pkg-1.0-py3-none-any.whl"
hashes = { sha256 = "..." }
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse, unquote

def wheel_filename_resolvable(name, path, url) -> bool:
    if name:
        return True
    if path and path.rsplit("/", 1)[-1]:
        return True
    if url:
        last = unquote(urlparse(url).path.rsplit("/", 1)[-1])
        return bool(last)
    return False

Try / catch

from packaging.pylock import Pylock, PylockValidationError

try:
    Pylock.from_dict(d)
except PylockValidationError as e:
    ...

Prevention

When it happens

Trigger: A wheel entry with no name, no path, and a url whose final path segment is empty (trailing-slash URL).

Common situations: Wheel URL missing the .whl filename component; forgetting 'name' when the source path/url has no basename.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/e7523a644702c49d. Report an issue: GitHub.

Appendix: source

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

    @classmethod
    def _from_dict(cls, d: Mapping[str, Any]) -> Self:
        package_wheel = cls(
            name=_get(d, str, "name"),
            upload_time=_get(d, datetime, "upload-time"),
            url=_get(d, str, "url"),
            path=_get(d, str, "path"),
            size=_get(d, int, "size"),
            hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"),  # type: ignore[type-abstract]
        )
        _validate_path_url(package_wheel.path, package_wheel.url)
        return package_wheel

    @property
    def filename(self) -> str:
        """Get the filename of the wheel."""
        filename = self.name or _path_name(self.path) or _url_name(self.url)
        if not filename:
            raise PylockValidationError("Cannot determine wheel filename")
        return filename


@dataclass(frozen=True, init=False)
class Package:
    name: NormalizedName
    version: Version | None = None
    marker: Marker | None = None
    requires_python: SpecifierSet | None = None
    dependencies: Sequence[Mapping[str, Any]] | None = None
    vcs: PackageVcs | None = None
    directory: PackageDirectory | None = None
    archive: PackageArchive | None = None
    index: str | None = None
    sdist: PackageSdist | None = None
    wheels: Sequence[PackageWheel] | None = None
    attestation_identities: Sequence[Mapping[str, Any]] | None = None
    tool: Mapping[str, Any] | None = None

View on GitHub (pinned to f399c37189)