pypa/pip · error · InvalidWheelFilename
Invalid wheel filename (extension must be '.whl')
Error message
Invalid wheel filename (extension must be '.whl'): {filename!r} What it means
Raised by parse_wheel_filename() when the filename does not end with the '.whl' extension. The wheel binary distribution format (PEP 427) mandates the .whl suffix, and this is the very first structural check at utils.py:255. The exception class is InvalidWheelFilename (a ValueError subclass).
Solutions
- Ensure the filename ends with '.whl' before calling parse_wheel_filename().
- If the file is a source distribution (.tar.gz or .zip), call parse_sdist_filename() instead.
- Strip directory components with os.path.basename() if you are passing full paths.
Example fix
// before
name, ver, build, tags = parse_wheel_filename('foo-1.0.tar.gz')
// after
name, ver = parse_sdist_filename('foo-1.0.tar.gz') Defensive patterns
Strategy: validation
Validate before calling
from packaging.utils import parse_wheel_filename, InvalidWheelFilename
def safe_parse_wheel(filename: str):
if not filename.endswith(".whl"):
raise ValueError(f"Not a wheel file: {filename!r}")
return parse_wheel_filename(filename) Type guard
def is_wheel_filename(filename: str) -> bool:
return isinstance(filename, str) and filename.endswith(".whl") Try / catch
from packaging.utils import InvalidWheelFilename
try:
name, ver, build, tags = parse_wheel_filename(filename)
except InvalidWheelFilename as e:
logger.warning("Skipping non-wheel file %s: %s", filename, e) Prevention
- Filter files by '.whl' extension before parsing
- Route .tar.gz/.zip files to parse_sdist_filename()
- Use os.path.basename() to isolate the filename from a path
When it happens
Trigger: Calling parse_wheel_filename() with a filename ending in '.tar.gz', '.zip', '.egg', or with no extension at all, e.g. parse_wheel_filename('foo-1.0.tar.gz') or parse_wheel_filename('foo-1.0-py3-none-any').
Common situations: Passing an sdist filename to the wheel parser by mistake, iterating over a mixed directory of wheels and sdists without filtering by extension, or a typo in the filename extension.
Related errors
- Invalid build number
- Invalid project name
- Invalid wheel filename (wrong number of parts)
- Invalid wheel filename (compressed tag set components must…
- Invalid wheel filename (invalid tag component)
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/b08b1f0258e7184b.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/utils.py:256
True
>>> not build
True
.. versionadded:: 20.9
.. versionchanged:: 23.2
Raises :class:`InvalidWheelFilename` when the version component is invalid.
.. versionadded:: 26.1
The *validate_order* parameter.
.. versionchanged:: 26.3
Raises :class:`InvalidWheelFilename` when an interpreter component is
not an identifier, a tag set component is empty, or the project name is
empty.
"""
if not filename.endswith(".whl"):
raise InvalidWheelFilename(
f"Invalid wheel filename (extension must be '.whl'): {filename!r}"
)
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 _wheel_name_regex.match(name_part) is None:
raise InvalidWheelFilename(f"Invalid project name: {filename!r}")
name = canonicalize_name(name_part)
try:View on GitHub (pinned to f399c37189)