{"id":"867ef34025f41698","repo":"pypa/pip","slug":"invalid-wheel-filename-wheel-filename-r","errorCode":null,"errorMessage":"Invalid wheel filename {wheel.filename!r}","messagePattern":"Invalid wheel filename (.+?)","errorType":"validation","errorClass":"PylockValidationError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/pylock.py","lineNumber":601,"sourceCode":"        )\n        distributions = bool(package.sdist) + len(package.wheels or [])\n        direct_urls = (\n            bool(package.vcs) + bool(package.directory) + bool(package.archive)\n        )\n        if distributions > 0 and direct_urls > 0:\n            raise PylockValidationError(\n                \"None of vcs, directory, archive must be set if sdist or wheels are set\"\n            )\n        if distributions == 0 and direct_urls != 1:\n            raise PylockValidationError(\n                \"Exactly one of vcs, directory, archive must be set \"\n                \"if sdist and wheels are not set\"\n            )\n        for i, wheel in enumerate(package.wheels or []):\n            try:\n                (name, version, _, _) = parse_wheel_filename(wheel.filename)\n            except Exception as e:\n                raise PylockValidationError(\n                    f\"Invalid wheel filename {wheel.filename!r}\",\n                    context=f\"wheels[{i}]\",\n                ) from e\n            if name != package.name:\n                raise PylockValidationError(\n                    f\"Name in {wheel.filename!r} is not consistent with \"\n                    f\"package name {package.name!r}\",\n                    context=f\"wheels[{i}]\",\n                )\n            if package.version and version != package.version:\n                raise PylockValidationError(\n                    f\"Version in {wheel.filename!r} is not consistent with \"\n                    f\"package version {str(package.version)!r}\",\n                    context=f\"wheels[{i}]\",\n                )\n        if package.sdist:\n            try:\n                name, version = parse_sdist_filename(package.sdist.filename)","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/pylock.py#L583-L619","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the wheel name/path/url to a valid PEP 427 filename: {distribution}-{version}-{python}-{abi}-{platform}.whl.","Regenerate the lockfile so the resolver records correct wheel filenames.","If setting path/url, ensure the basename is the wheel filename.","Catch the error and report the bad filename and wheel index (context)."],"exampleFix":"# before\n[[packages.wheels]]\nname = \\\"foo-1.0\\\"\n# after\n[[packages.wheels]]\nname = \\\"foo-1.0-py3-none-any.whl\\\"","handlingStrategy":"validation","validationCode":"from packaging.utils import parse_wheel_filename\n\ndef is_valid_wheel_name(fname: str) -> bool:\n    try:\n        parse_wheel_filename(fname)\n        return True\n    except Exception:\n        return False","typeGuard":"import re\nfrom packaging.utils import parse_wheel_filename\n\ndef is_wheel_filename(s: str) -> bool:\n    if not isinstance(s, str) or not s.endswith('.whl'):\n        return False\n    try:\n        parse_wheel_filename(s)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"try:\n    PylockFile.from_dict(data)\nexcept PylockValidationError as e:\n    if 'Invalid wheel filename' in str(e):\n        repair_wheel_name(e.context)","preventionTips":["Use full PEP 427 wheel filenames: {dist}-{version}-{py}-{abi}-{plat}.whl.","Validate with parse_wheel_filename before persisting.","Ensure path/url basenames are valid wheel filenames.","Catch and surface e.context (wheel index)."],"tags":["pylock","pep771","wheel","pep427","validation"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}