{"record":{"id":"6e91aa34716905e7","repo":"pypa/pip","slug":"tag-tag-r-has-an-invalid-interpreter-interpret","errorCode":null,"errorMessage":"Tag {tag!r} has an invalid interpreter: {interpreter!r}","messagePattern":"Tag (.+?) has an invalid interpreter: (.+?)","errorType":"validation","errorClass":"InvalidTag","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/tags.py","lineNumber":304,"sourceCode":"            )\n\n    tag_count = 1\n    for parts in component_parts:\n        tag_count *= len(parts)\n\n    if limit is not None and tag_count > limit:\n        raise TooManyTagsError(\n            f\"Compressed tag set would generate {tag_count} tags, exceeding \"\n            f\"limit {limit}\"\n        )\n\n    try:\n        interpreters, abis, platforms = component_parts\n    except ValueError as exc:\n        raise InvalidTag(f\"Tag {tag!r} must have exactly three components\") from exc\n    for interpreter in interpreters:\n        if not interpreter.isidentifier():\n            raise InvalidTag(f\"Tag {tag!r} has an invalid interpreter: {interpreter!r}\")\n    return frozenset(\n        Tag(interpreter, abi, platform_)\n        for interpreter in interpreters\n        for abi in abis\n        for platform_ in platforms\n    )\n\n\ndef _get_config_var(name: str, warn: bool = False) -> int | str | None:\n    value: int | str | None = sysconfig.get_config_var(name)\n    if value is None and warn:\n        logger.debug(\n            \"Config variable '%s' is unset, Python ABI tag may be incorrect\", name\n        )\n    return value\n\n\ndef _normalize_string(string: str) -> str:","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/tags.py#L286-L322","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nparse_tag('310-cp310-linux_x86_64')  # '310'.isidentifier() is False -> InvalidTag\n\n# after - prefix the interpreter token\nparse_tag('cp310-cp310-linux_x86_64')  # 'cp310' is a valid identifier","handlingStrategy":"validation","validationCode":"def valid_interpreters(tag: str) -> bool:\n    interp = tag.split('-')[0]\n    return all(t.isidentifier() for t in interp.split('.'))","typeGuard":"def is_identifier_token(t: str) -> bool:\n    return t.isidentifier()","tryCatchPattern":"from packaging.tags import InvalidTag\ntry:\n    parse_tag(tag)\nexcept InvalidTag as e:\n    if 'invalid interpreter' in str(e):\n        fix_interpreter_prefix(tag)","preventionTips":["Prefix numeric interpreter tokens with py/cp.","Validate each alternative with .isidentifier().","Strip whitespace/symbols from interpreter fields."],"tags":["packaging","tags","validation","pep425","identifier"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}