{"record":{"id":"e7523a644702c49d","repo":"pypa/pip","slug":"cannot-determine-wheel-filename","errorCode":null,"errorMessage":"Cannot determine wheel filename","messagePattern":"Cannot determine wheel filename","errorType":"validation","errorClass":"PylockValidationError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/pylock.py","lineNumber":531,"sourceCode":"    @classmethod\n    def _from_dict(cls, d: Mapping[str, Any]) -> Self:\n        package_wheel = cls(\n            name=_get(d, str, \"name\"),\n            upload_time=_get(d, datetime, \"upload-time\"),\n            url=_get(d, str, \"url\"),\n            path=_get(d, str, \"path\"),\n            size=_get(d, int, \"size\"),\n            hashes=_get_required_as(d, Mapping, _validate_hashes, \"hashes\"),  # type: ignore[type-abstract]\n        )\n        _validate_path_url(package_wheel.path, package_wheel.url)\n        return package_wheel\n\n    @property\n    def filename(self) -> str:\n        \"\"\"Get the filename of the wheel.\"\"\"\n        filename = self.name or _path_name(self.path) or _url_name(self.url)\n        if not filename:\n            raise PylockValidationError(\"Cannot determine wheel filename\")\n        return filename\n\n\n@dataclass(frozen=True, init=False)\nclass Package:\n    name: NormalizedName\n    version: Version | None = None\n    marker: Marker | None = None\n    requires_python: SpecifierSet | None = None\n    dependencies: Sequence[Mapping[str, Any]] | None = None\n    vcs: PackageVcs | None = None\n    directory: PackageDirectory | None = None\n    archive: PackageArchive | None = None\n    index: str | None = None\n    sdist: PackageSdist | None = None\n    wheels: Sequence[PackageWheel] | None = None\n    attestation_identities: Sequence[Mapping[str, Any]] | None = None\n    tool: Mapping[str, Any] | None = None","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/pylock.py#L513-L549","documentation":"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.","triggerScenarios":"A wheel entry with no name, no path, and a url whose final path segment is empty (trailing-slash URL).","commonSituations":"Wheel URL missing the .whl filename component; forgetting 'name' when the source path/url has no basename.","solutions":["Set name = \"pkg-1.0-py3-none-any.whl\" explicitly, or","Make the url/path end in the wheel filename (remove trailing slash)."],"exampleFix":"# before\n[[packages.wheels]]\nurl = \"https://example.com/\"\nhashes = { sha256 = \"...\" }\n# after\n[[packages.wheels]]\nname = \"pkg-1.0-py3-none-any.whl\"\nhashes = { sha256 = \"...\" }","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse, unquote\n\ndef wheel_filename_resolvable(name, path, url) -> bool:\n    if name:\n        return True\n    if path and path.rsplit(\"/\", 1)[-1]:\n        return True\n    if url:\n        last = unquote(urlparse(url).path.rsplit(\"/\", 1)[-1])\n        return bool(last)\n    return False\n","typeGuard":null,"tryCatchPattern":"from packaging.pylock import Pylock, PylockValidationError\n\ntry:\n    Pylock.from_dict(d)\nexcept PylockValidationError as e:\n    ...\n","preventionTips":["Set an explicit wheel 'name' (the full .whl filename) on wheel entries.","Make wheel URLs end in the .whl filename."],"tags":["pylock","wheel","validation","filename"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}