{"id":"296d5f8112de648e","repo":"pypa/pip","slug":"invalid-wheel-filename-invalid-version-filenam","errorCode":null,"errorMessage":"Invalid wheel filename (invalid version): {filename!r}","messagePattern":"Invalid wheel filename \\(invalid version\\): (.+?)","errorType":"validation","errorClass":"InvalidWheelFilename","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/utils.py","lineNumber":224,"sourceCode":"\n    filename = filename[:-4]\n    dashes = filename.count(\"-\")\n    if dashes not in (4, 5):\n        raise InvalidWheelFilename(\n            f\"Invalid wheel filename (wrong number of parts): {filename!r}\"\n        )\n\n    parts = filename.split(\"-\", dashes - 2)\n    name_part = parts[0]\n    # See PEP 427 for the rules on escaping the project name.\n    if \"__\" in name_part or re.match(r\"^[\\w\\d._]*$\", name_part, re.UNICODE) is None:\n        raise InvalidWheelFilename(f\"Invalid project name: {filename!r}\")\n    name = canonicalize_name(name_part)\n\n    try:\n        version = Version(parts[1])\n    except InvalidVersion as e:\n        raise InvalidWheelFilename(\n            f\"Invalid wheel filename (invalid version): {filename!r}\"\n        ) from e\n\n    if dashes == 5:\n        build_part = parts[2]\n        build_match = _build_tag_regex.match(build_part)\n        if build_match is None:\n            raise InvalidWheelFilename(\n                f\"Invalid build number: {build_part} in {filename!r}\"\n            )\n        build = cast(\"BuildTag\", (int(build_match.group(1)), build_match.group(2)))\n    else:\n        build = ()\n    tag_str = parts[-1]\n    try:\n        tags = parse_tag(tag_str, validate_order=validate_order)\n    except UnsortedTagsError:\n        raise InvalidWheelFilename(","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/utils.py#L206-L242","documentation":"Raised by `parse_wheel_filename` when the version segment of the filename cannot be parsed as a PEP 440 version via `Version(parts[1])`. The parser catches the underlying `InvalidVersion` and re-raises it as `InvalidWheelFilename`, so the cause is attached via `from e`. Wheel filenames must carry a valid PEP 440 version in the second dash-separated position.","triggerScenarios":"A version segment like `1.0.0.0.0.0` (too many components is fine but unusual punctuation is not), `1.0.beta` (wrong pre-release separator), `v1.0` (leading 'v'), `1.0..2` (empty), or any non-PEP-440 string in the version slot.","commonSituations":"A wheel built from a project whose version was set to a non-PEP-440 string (git-describe output, a leading 'v', date schemes like `2024.03.05.rc1` with bad punctuation); renaming that corrupted the version; upstream packages with sloppy versions.","solutions":["Set the project version to a PEP 440-compliant string (`1.0`, `1.0a1`, `1.0.post1`, `1.0+local`).","Strip a leading `v` from the version before build, or configure setuptools to do so.","Use `Version(version_str)` directly to surface the precise `InvalidVersion` reason, then fix it.","Re-fetch the wheel from the index if it was externally produced and malformed."],"exampleFix":"// before\nparse_wheel_filename('foo-v1.0-py3-none-any.whl')  # 'v1.0' not PEP 440\n\n# after\nparse_wheel_filename('foo-1.0-py3-none-any.whl')","handlingStrategy":"try-catch","validationCode":"from pip._vendor.packaging.version import Version, InvalidVersion\n\ndef has_valid_wheel_version(filename: str) -> bool:\n    if not filename.endswith('.whl'):\n        return False\n    stem = filename[:-4]\n    # version is the segment after the first dash in the split scheme\n    parts = stem.split('-', stem.count('-') - 2)\n    try:\n        Version(parts[1])\n        return True\n    except InvalidVersion:\n        return False","typeGuard":null,"tryCatchPattern":"from pip._vendor.packaging.utils import parse_wheel_filename, InvalidWheelFilename\n\ntry:\n    name, ver, build, tags = parse_wheel_filename(filename)\nexcept InvalidWheelFilename as e:\n    if 'invalid version' in str(e):\n        # fix the project version to PEP 440, then rebuild\n        ...\n    raise","preventionTips":["Keep project versions PEP 440-compliant (no leading `v`, correct pre/post/dev syntax).","Use setuptools-scm or a version bumper to normalize VCS tags to PEP 440.","Pre-validate the version segment with `Version()` in isolation to get a precise error."],"tags":["python","packaging","utils","wheel","pep427","version","pep440"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}