nodejs/node · error · InvalidWheelFilename

Invalid build number: {build_part} in '{filename}'

Error message

Invalid build number: {build_part} in '{filename}'

What it means

InvalidWheelFilename raised when the wheel has 5 dashes (a build tag is present) but parts[2] does not match the build-tag regex (\d+)(.*) - i.e. it does not start with a digit. PEP 427 requires the build number to begin with an integer.

Source

Thrown at tools/gyp/pylib/packaging/utils.py:136

    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:
        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}'"
            )
        build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2)))
    else:
        build = ()
    tags = parse_tag(parts[-1])
    return (name, version, build, tags)


def parse_sdist_filename(filename: str) -> Tuple[NormalizedName, Version]:
    if filename.endswith(".tar.gz"):
        file_stem = filename[: -len(".tar.gz")]
    elif filename.endswith(".zip"):
        file_stem = filename[: -len(".zip")]
    else:
        raise InvalidSdistFilename(
            f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
            f" {filename}"

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Format build tags as an integer optionally followed by a suffix, e.g. '7', '1.post', '3local'.
  2. Drop the build tag entirely (use 4-dash form) if you do not need it.
  3. Rebuild with a conformant backend.

Example fix

# before
# 'mypkg-1.0.0-build7-py3-none-any.whl'

# after
# 'mypkg-1.0.0-7-py3-none-any.whl'
Defensive patterns

Strategy: validation

Validate before calling

import re
_build_re = re.compile(r'(\d+)(.*)')
def valid_build_tag(filename: str) -> bool:
    parts = filename[:-4].split('-')
    if len(parts) != 6:
        return True  # no build tag present
    return bool(_build_re.match(parts[2]))

Try / catch

try:
    parse_wheel_filename(fn)
except InvalidWheelFilename as e:
    if 'build number' in str(e):
        pass  # drop or fix the build tag, rebuild

Prevention

When it happens

Trigger: A wheel filename like 'mypkg-1.0.0-build7-py3-none-any.whl' where the build segment starts with a letter instead of a digit.

Common situations: Manually adding a build tag that violates the leading-digit rule, or a build backend bug that emits an invalid build tag.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/2199e80cf6d8075a. Report an issue: GitHub.