python-poetry/poetry · error · ValueError

Unable to parse build tag: {wheel.build_tag}

Error message

Unable to parse build tag: {wheel.build_tag}

What it means

Raised by Chooser._sort_key at src/poetry/installation/chooser.py:307-309 when a wheel's build_tag is present but does not match the regex `^(\d+)(.*)$`. Build tags must be an integer followed by an optional label (PEP 427); anything else is a malformed filename. ValueError.

Source

Thrown at src/poetry/installation/chooser.py:309

              comparison operators, but then different sdist links
              with the same version, would have to be considered equal
        """
        build_tag: tuple[Any, ...] = ()
        binary_preference = 0
        if link.is_wheel:
            wheel = Wheel(link.filename)
            if not wheel.is_supported_by_environment(self._env):
                raise RuntimeError(
                    f"{wheel.filename} is not a supported wheel for this platform. It "
                    "can't be sorted."
                )

            # TODO: Binary preference
            pri = -(wheel.get_minimum_supported_index(self._env.supported_tags) or 0)
            if wheel.build_tag is not None:
                match = re.match(r"^(\d+)(.*)$", wheel.build_tag)
                if not match:
                    raise ValueError(f"Unable to parse build tag: {wheel.build_tag}")
                build_tag_groups = match.groups()
                build_tag = (int(build_tag_groups[0]), build_tag_groups[1])
        else:  # sdist
            support_num = len(self._env.supported_tags)
            pri = -support_num

        has_allowed_hash = int(self._is_link_hash_allowed_for_package(link, package))

        yank_value = int(not link.yanked)

        return (
            has_allowed_hash,
            yank_value,
            binary_preference,
            package.version,
            build_tag,
            pri,
        )

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Inspect the wheel filename and confirm the build-tag segment (after version, before python tag) is digits-only optionally followed by a label.
  2. Rebuild/rename the wheel to comply with PEP 427 (e.g. `pkg-1.0-1-py3-none-any.whl`).
  3. Remove the malformed wheel from the index if it is not yours to fix.

Example fix

# before (malformed)
pkg-1.0-abc-py3-none-any.whl

# after
pkg-1.0-1-py3-none-any.whl
Defensive patterns

Strategy: validation

Validate before calling

import re

def valid_build_tag(build_tag: str | None) -> bool:
    return build_tag is None or bool(re.match(r'^(\d+)(.*)$', build_tag))

Try / catch

try:
    sorted(candidates, key=chooser._sort_key)
except ValueError as e:
    if 'Unable to parse build tag' in str(e):
        # skip the malformed wheel from the candidate set
        candidates = [c for c in candidates if not has_bad_build_tag(c.link)]
        sorted(candidates, key=chooser._sort_key)
    raise

Prevention

When it happens

Trigger: A wheel filename like `pkg-1.0-abc-py3-none-any.whl` where the build tag segment is non-numeric. Wheel(link.filename).build_tag is non-None (so the segment exists) but the leading characters are not digits.

Common situations: A private index hosting a hand-renamed wheel, a packaging tool emitting non-standard build tags, or a filename collision that looks like a build tag.

Related errors


AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04). Data as JSON: /data/errors/dda11911bd4e24b7.json. Report an issue: GitHub.