{"record":{"id":"62d379c920348f7e","repo":"pypa/pip","slug":"tag-tag-r-has-an-empty-component-component-r","errorCode":null,"errorMessage":"Tag {tag!r} has an empty component: {component!r}","messagePattern":"Tag (.+?) has an empty component: (.+?)","errorType":"validation","errorClass":"InvalidTag","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/tags.py","lineNumber":281,"sourceCode":"    .. versionadded:: 26.1\n       The *validate_order* parameter.\n\n    .. versionadded:: 26.3\n       Raises :class:`InvalidTag` when an interpreter component is not an\n       identifier, a tag component is empty, or a tag does not have exactly\n       three components.\n       Added the *limit* parameter. Raises :class:`TooManyTagsError` if the compressed\n       tag set would generate more than *limit* tags.\n    \"\"\"\n\n    if limit is not None and limit < 0:\n        raise ValueError(\"limit must be non-negative\")\n\n    component_parts = [component.split(\".\") for component in tag.split(\"-\")]\n    for parts in component_parts:\n        if \"\" in parts:\n            component = \".\".join(parts)\n            raise InvalidTag(f\"Tag {tag!r} has an empty component: {component!r}\")\n        if validate_order and parts != sorted(parts):\n            component = \".\".join(parts)\n            raise UnsortedTagsError(\n                f\"Tag component {component!r} is not in sorted order per PEP 425\"\n            )\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","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/tags.py#L263-L299","documentation":"Raised as InvalidTag (ValueError subclass) by parse_tag (tags.py:279-281) when splitting a component on '.' yields an empty string, meaning the tag has an empty component. This catches leading/trailing dots, double dots, or a leading/trailing hyphen that produces an empty component group. The reported component is the '.'-joined part that contained the gap.","triggerScenarios":"parse_tag('py3-.cpython310-any') (leading dot in a component); parse_tag('py3-cp310-') (trailing hyphen -> empty platform group); parse_tag('py3-..-any'); parse_tag('-none-any') (leading hyphen).","commonSituations":"Malformed wheel tag strings read from a filename or index; programmatic tag assembly with f-strings where a field was empty (f'{interp}-{abi}-{plat}' with plat=''); user input for a custom platform tag with stray punctuation.","solutions":["Sanitize/validate the tag string before calling parse_tag: ensure no leading/trailing '-' or '.', no consecutive '.' or '-'.","Build tags from non-empty parts only; skip empty components in the generator.","Use the Tag(interpreter, abi, platform) constructor with pre-validated non-empty strings instead of parse_tag for single tags.","Catch InvalidTag and report the offending tag string to the user/operator."],"exampleFix":"# before\nparse_tag(f'{interp}-{abi}-{plat}')  # plat='' -> InvalidTag: empty component\n\n# after - validate non-empty parts\nparts = [interp, abi, plat]\nassert all(parts), 'tag components must be non-empty'\nparse_tag('-'.join(parts))","handlingStrategy":"validation","validationCode":"import re\ndef is_well_formed_tag(tag: str) -> bool:\n    # no empty components: no leading/trailing - or ., no consecutive separators\n    return bool(tag) and not re.search(r'(?:^|[-.])[-.](?:[-.]|$)', tag)","typeGuard":null,"tryCatchPattern":"from packaging.tags import InvalidTag\ntry:\n    parse_tag(tag)\nexcept InvalidTag:\n    handle_bad_tag(tag)","preventionTips":["Build tags from non-empty parts; assert all(parts).","Normalize stray punctuation before parse_tag.","Use the Tag(interpreter, abi, platform) constructor for single tags."],"tags":["packaging","tags","validation","pep425"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}