pypa/pip · error · InvalidTag

Tag {tag!r} has an invalid interpreter: {interpreter!r}

Error message

Tag {tag!r} has an invalid interpreter: {interpreter!r}

What it means

Raised as InvalidTag (ValueError subclass) by parse_tag (tags.py:302-304) when any interpreter component fails str.isidentifier(). Per the versionadded note (26.3), the interpreter field must be a valid Python identifier, so tokens starting with a digit, containing spaces/special chars, or otherwise non-identifier are rejected. Each alternative in a compressed interpreter component (e.g. 'py2.py3') is checked.

Source

Thrown at src/pip/_vendor/packaging/tags.py:304

            )

    tag_count = 1
    for parts in component_parts:
        tag_count *= len(parts)

    if limit is not None and tag_count > limit:
        raise TooManyTagsError(
            f"Compressed tag set would generate {tag_count} tags, exceeding "
            f"limit {limit}"
        )

    try:
        interpreters, abis, platforms = component_parts
    except ValueError as exc:
        raise InvalidTag(f"Tag {tag!r} must have exactly three components") from exc
    for interpreter in interpreters:
        if not interpreter.isidentifier():
            raise InvalidTag(f"Tag {tag!r} has an invalid interpreter: {interpreter!r}")
    return frozenset(
        Tag(interpreter, abi, platform_)
        for interpreter in interpreters
        for abi in abis
        for platform_ in platforms
    )


def _get_config_var(name: str, warn: bool = False) -> int | str | None:
    value: int | str | None = sysconfig.get_config_var(name)
    if value is None and warn:
        logger.debug(
            "Config variable '%s' is unset, Python ABI tag may be incorrect", name
        )
    return value


def _normalize_string(string: str) -> str:

View on GitHub (pinned to f399c37189)

Solutions

  1. Prefix numeric interpreter tokens appropriately (e.g. 'py3', 'cp310') so they are valid identifiers.
  2. Validate each alternative with token.isidentifier() before assembling the tag string.
  3. Strip whitespace and disallowed characters from interpreter fields.
  4. Catch InvalidTag and report the specific offending interpreter token.

Example fix

# before
parse_tag('310-cp310-linux_x86_64')  # '310'.isidentifier() is False -> InvalidTag

# after - prefix the interpreter token
parse_tag('cp310-cp310-linux_x86_64')  # 'cp310' is a valid identifier
Defensive patterns

Strategy: validation

Validate before calling

def valid_interpreters(tag: str) -> bool:
    interp = tag.split('-')[0]
    return all(t.isidentifier() for t in interp.split('.'))

Type guard

def is_identifier_token(t: str) -> bool:
    return t.isidentifier()

Try / catch

from packaging.tags import InvalidTag
try:
    parse_tag(tag)
except InvalidTag as e:
    if 'invalid interpreter' in str(e):
        fix_interpreter_prefix(tag)

Prevention

When it happens

Trigger: parse_tag('3-none-any') ('3'.isidentifier() is False); parse_tag('py 3-none-any') (space); parse_tag('cp310.3-...') where an alternative starts with a digit; any interpreter token with a leading digit or disallowed character.

Common situations: Constructing tags from raw version numbers without the 'py'/'cp' prefix; a tag generator that emitted a numeric-only interpreter; user-supplied interpreter names with whitespace or symbols.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/6e91aa34716905e7. Report an issue: GitHub.