{"record":{"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":277,"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 _wheel_name_regex.match(name_part) 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":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/utils.py#L259-L295","documentation":"Raised by parse_wheel_filename() when the version segment of the wheel stem cannot be parsed by Version() (utils.py:274-279). The inner InvalidVersion from version.py is caught and re-raised as InvalidWheelFilename. The version must conform to PEP 440.","triggerScenarios":"A wheel filename whose second dash-separated component is not a valid PEP 440 version, e.g. 'foo-notaversion-py3-none-any.whl' where 'notaversion' fails Version() parsing.","commonSituations":"Non-PEP-440 version schemes (e.g. SemVer-only dates like '20230101-rc1' with unexpected format), or a build tool that emits a version string not understood by packaging's Version class.","solutions":["Verify the version segment is a valid PEP 440 version string.","Test the version with Version(version_str) in isolation to get the precise parse error.","Normalize the version string to PEP 440 before building the wheel."],"exampleFix":"// before\nparse_wheel_filename('foo-1.0.alpha-py3-none-any.whl')  // '1.0.alpha' is not PEP 440\n// after\nparse_wheel_filename('foo-1.0a1-py3-none-any.whl')","handlingStrategy":"try-catch","validationCode":"from packaging.version import Version, InvalidVersion\n\ndef safe_parse_wheel(filename: str):\n    stem = filename[:-4]\n    version_str = stem.split(\"-\", 2)[1]\n    try:\n        Version(version_str)\n    except InvalidVersion:\n        raise ValueError(f\"Invalid version {version_str!r} in wheel {filename!r}\")\n    return parse_wheel_filename(filename)","typeGuard":"from packaging.version import Version\n\ndef has_valid_wheel_version(filename: str) -> bool:\n    if not isinstance(filename, str) or not filename.endswith(\".whl\"):\n        return False\n    try:\n        Version(filename[:-4].split(\"-\", 2)[1])\n        return True\n    except Exception:\n        return False","tryCatchPattern":"from packaging.utils import InvalidWheelFilename\n\ntry:\n    name, ver, build, tags = parse_wheel_filename(filename)\nexcept InvalidWheelFilename as e:\n    if \"invalid version\" in str(e):\n        logger.error(\"Wheel version is not PEP 440 compliant: %s\", filename)\n    raise","preventionTips":["Test the version segment with Version() in isolation first","Ensure the build tool produces PEP 440-compliant versions","Normalize version strings before constructing wheel filenames"],"tags":["wheel","filename","version","packaging","pep440"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}