pypa/pip · error · InvalidWheelFilename
Invalid wheel filename (invalid tag component): {filename!r}
Error message
Invalid wheel filename (invalid tag component): {filename!r} What it means
Raised by parse_wheel_filename() when parse_tag() raises InvalidTag (utils.py:299-302). This covers three cases per tags.py:301-304: the tag string does not have exactly three dash-separated components, any component is empty (e.g. trailing dash or double dash), or an interpreter component is not a valid Python identifier.
Source
Thrown at src/pip/_vendor/packaging/utils.py:300
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(
f"Invalid wheel filename (compressed tag set components must be in "
f"sorted order per PEP 425): {filename!r}"
) from None
except InvalidTag:
raise InvalidWheelFilename(
f"Invalid wheel filename (invalid tag component): {filename!r}"
) from None
return (name, version, build, tags)
def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]:
"""
This function takes the filename of a sdist file (as specified
in the `Source distribution format`_ documentation), and parses
it, returning a tuple of the normalized name and version as
represented by an instance of :class:`~packaging.version.Version`.
:param str filename: The name of the sdist file.
:raises InvalidSdistFilename: If the filename does not end
with an sdist extension (``.zip`` or ``.tar.gz``), if it does not
contain a dash separating the name and the version of the distribution,
if the project name is empty, or if the version portion is not a valid
version.View on GitHub (pinned to f399c37189)
Solutions
- Ensure the tag portion has exactly three components: {pythontag}-{abitag}-{platformtag}.
- Remove any empty components (no double dashes or trailing dashes).
- Verify the interpreter tag starts with a letter or underscore (must be a valid Python identifier).
Example fix
// before
parse_wheel_filename('foo-1.0-py3-none-any-extra.whl') // 4 tag components
// after
parse_wheel_filename('foo-1.0-py3-none-any.whl') Defensive patterns
Strategy: validation
Validate before calling
def safe_parse_wheel(filename: str):
stem = filename[:-4]
tag_str = stem.rsplit("-", 3)[-1]
components = tag_str.split("-")
if len(components) != 3:
raise ValueError(f"Tag must have 3 components: {tag_str!r}")
for comp in components:
if "" in comp.split("."):
raise ValueError(f"Empty tag component in: {tag_str!r}")
for interp in components[0].split("."):
if not interp.isidentifier():
raise ValueError(f"Invalid interpreter tag: {interp!r}")
return parse_wheel_filename(filename) Type guard
def is_valid_tag_string(tag_str: str) -> bool:
parts = tag_str.split("-")
if len(parts) != 3:
return False
for component in parts:
if "" in component.split("."):
return False
return all(interp.isidentifier() for interp in parts[0].split(".")) Try / catch
from packaging.utils import InvalidWheelFilename
try:
name, ver, build, tags = parse_wheel_filename(filename)
except InvalidWheelFilename as e:
if "invalid tag component" in str(e):
logger.error("Malformed tag in wheel: %s", filename)
raise Prevention
- Verify the tag portion has exactly three dash-separated components
- Ensure no empty components (no double dashes)
- Check that the interpreter tag starts with a letter or underscore (valid Python identifier)
When it happens
Trigger: A wheel filename whose tag portion is malformed: 'foo-1.0-py3-none-any-extra.whl' (4 components), 'foo-1.0-py3--any.whl' (empty ABI), or 'foo-1.0-3py-none-any.whl' (interpreter '3py' is not a valid identifier because it starts with a digit).
Common situations: Hand-crafted wheel filenames with wrong tag structure, a platform tag containing a stray dash, or a build tool that omits or duplicates a tag component.
Related errors
- Invalid wheel filename (compressed tag set components must b
- Invalid wheel filename {wheel.filename!r}
- No wheel found matching the provided tags for package {packa
- Tag {tag!r} has an empty component: {component!r}
- Tag component {component!r} is not in sorted order per PEP 4
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/cb8e16e4049defdc.
Report an issue: GitHub.