pypa/pip · error · InvalidWheelFilename
Invalid wheel filename (invalid version): {filename!r}
Error message
Invalid wheel filename (invalid version): {filename!r} What it means
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.
Source
Thrown at src/pip/_vendor/packaging/utils.py:224
filename = filename[:-4]
dashes = filename.count("-")
if dashes not in (4, 5):
raise InvalidWheelFilename(
f"Invalid wheel filename (wrong number of parts): {filename!r}"
)
parts = filename.split("-", dashes - 2)
name_part = parts[0]
# See PEP 427 for the rules on escaping the project name.
if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None:
raise InvalidWheelFilename(f"Invalid project name: {filename!r}")
name = canonicalize_name(name_part)
try:
version = Version(parts[1])
except InvalidVersion as e:
raise InvalidWheelFilename(
f"Invalid wheel filename (invalid version): {filename!r}"
) from e
if dashes == 5:
build_part = parts[2]
build_match = _build_tag_regex.match(build_part)
if build_match is None:
raise InvalidWheelFilename(
f"Invalid build number: {build_part} in {filename!r}"
)
build = cast("BuildTag", (int(build_match.group(1)), build_match.group(2)))
else:
build = ()
tag_str = parts[-1]
try:
tags = parse_tag(tag_str, validate_order=validate_order)
except UnsortedTagsError:
raise InvalidWheelFilename(View on GitHub (pinned to d7d0d0a394)
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.
Example fix
// before
parse_wheel_filename('foo-v1.0-py3-none-any.whl') # 'v1.0' not PEP 440
# after
parse_wheel_filename('foo-1.0-py3-none-any.whl') Defensive patterns
Strategy: try-catch
Validate before calling
from pip._vendor.packaging.version import Version, InvalidVersion
def has_valid_wheel_version(filename: str) -> bool:
if not filename.endswith('.whl'):
return False
stem = filename[:-4]
# version is the segment after the first dash in the split scheme
parts = stem.split('-', stem.count('-') - 2)
try:
Version(parts[1])
return True
except InvalidVersion:
return False Try / catch
from pip._vendor.packaging.utils import parse_wheel_filename, InvalidWheelFilename
try:
name, ver, build, tags = parse_wheel_filename(filename)
except InvalidWheelFilename as e:
if 'invalid version' in str(e):
# fix the project version to PEP 440, then rebuild
...
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid wheel filename (extension must be '.whl'): {filename
- Invalid wheel filename (wrong number of parts): {filename!r}
- Invalid project name: {filename!r}
- Invalid build number: {build_part} in {filename!r}
- Invalid sdist filename (invalid version): {filename!r}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/296d5f8112de648e.json.
Report an issue: GitHub.