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
- Prefix numeric interpreter tokens appropriately (e.g. 'py3', 'cp310') so they are valid identifiers.
- Validate each alternative with token.isidentifier() before assembling the tag string.
- Strip whitespace and disallowed characters from interpreter fields.
- 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
- Prefix numeric interpreter tokens with py/cp.
- Validate each alternative with .isidentifier().
- Strip whitespace/symbols from interpreter fields.
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
- Tag {tag!r} has an empty component: {component!r}
- Tag component {component!r} is not in sorted order per PEP 4
- Tag {tag!r} must have exactly three components
- limit must be non-negative
- Compressed tag set would generate {tag_count} tags, exceedin
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/6e91aa34716905e7.
Report an issue: GitHub.