nodejs/node · error · InvalidWheelFilename
Invalid wheel filename (wrong number of parts): {filename}
Error message
Invalid wheel filename (wrong number of parts): {filename} What it means
InvalidWheelFilename raised when, after stripping '.whl', the stem does not contain exactly 4 or 5 dashes (the PEP 427 layout is name-version-(build)-python-abi-platform). 4 dashes = no build tag, 5 dashes = build tag present; anything else is structurally invalid.
Source
Thrown at tools/gyp/pylib/packaging/utils.py:114
# Local version segment
if parsed.local is not None:
parts.append(f"+{parsed.local}")
return "".join(parts)
def parse_wheel_filename(
filename: str,
) -> Tuple[NormalizedName, Version, BuildTag, FrozenSet[Tag]]:
if not filename.endswith(".whl"):
raise InvalidWheelFilename(
f"Invalid wheel filename (extension must be '.whl'): {filename}"
)
filename = filename[:-4]
dashes = filename.count("-")
if dashes not in (4, 5):
raise InvalidWheelFilename(
f"Invalid wheel filename (wrong number of parts): {filename}"
)
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}")
name = canonicalize_name(name_part)
try:
version = Version(parts[1])
except InvalidVersion as e:
raise InvalidWheelFilename(
f"Invalid wheel filename (invalid version): {filename}"
) from e
if dashes == 5:View on GitHub (pinned to 1b2de5e052)
Solutions
- Confirm the wheel was built by a standard PEP 517 backend (build, hatchling, setuptools) rather than renamed by hand.
- Ensure project names with dashes are escaped to underscores in the wheel filename (the backend does this automatically).
- Rebuild the wheel from source instead of editing the filename.
Example fix
# before (manually renamed, name dash not escaped) # 'my-pkg-1.0-py3-none-any.whl' # after (backend rebuild emits escaped name) # 'my_pkg-1.0-py3-none-any.whl'
Defensive patterns
Strategy: validation
Validate before calling
def has_wheel_dash_count(filename: str) -> bool:
if not filename.endswith('.whl'):
return False
return filename[:-4].count('-') in (4, 5) Try / catch
try:
name, ver, build, tags = parse_wheel_filename(fn)
except InvalidWheelFilename as e:
if 'wrong number of parts' in str(e):
pass # log and skip non-conformant wheel Prevention
- Build wheels only with PEP 517 backends.
- Never hand-rename wheel files.
- Escape dashes in project names to underscores in wheel filenames.
When it happens
Trigger: A filename like 'foo-1.0-py3-none-any-extra-junk.whl' (6 dashes) or 'foo-py3-none-any.whl' (3 dashes, missing version), or any wheel whose name/version/tag components themselves contain stray dashes.
Common situations: Hand-renamed wheel files, names with unescaped dashes that should have been replaced with underscores per PEP 427, or wheels produced by non-compliant build tools.
Related errors
- Invalid wheel filename (extension must be '.whl'): {filename
- Invalid project name: {filename}
- Invalid wheel filename (invalid version): {filename}
- Invalid build number: {build_part} in '{filename}'
- Invalid sdist filename (extension must be '.tar.gz' or '.zip
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/3ca6ba394326077f.
Report an issue: GitHub.