pypa/pip · error · InvalidTag
Tag {tag!r} has an empty component: {component!r}
Error message
Tag {tag!r} has an empty component: {component!r} What it means
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.
Source
Thrown at src/pip/_vendor/packaging/tags.py:281
.. versionadded:: 26.1
The *validate_order* parameter.
.. versionadded:: 26.3
Raises :class:`InvalidTag` when an interpreter component is not an
identifier, a tag component is empty, or a tag does not have exactly
three components.
Added the *limit* parameter. Raises :class:`TooManyTagsError` if the compressed
tag set would generate more than *limit* tags.
"""
if limit is not None and limit < 0:
raise ValueError("limit must be non-negative")
component_parts = [component.split(".") for component in tag.split("-")]
for parts in component_parts:
if "" in parts:
component = ".".join(parts)
raise InvalidTag(f"Tag {tag!r} has an empty component: {component!r}")
if validate_order and parts != sorted(parts):
component = ".".join(parts)
raise UnsortedTagsError(
f"Tag component {component!r} is not in sorted order per PEP 425"
)
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_partsView on GitHub (pinned to f399c37189)
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.
Example fix
# before
parse_tag(f'{interp}-{abi}-{plat}') # plat='' -> InvalidTag: empty component
# after - validate non-empty parts
parts = [interp, abi, plat]
assert all(parts), 'tag components must be non-empty'
parse_tag('-'.join(parts)) Defensive patterns
Strategy: validation
Validate before calling
import re
def is_well_formed_tag(tag: str) -> bool:
# no empty components: no leading/trailing - or ., no consecutive separators
return bool(tag) and not re.search(r'(?:^|[-.])[-.](?:[-.]|$)', tag) Try / catch
from packaging.tags import InvalidTag
try:
parse_tag(tag)
except InvalidTag:
handle_bad_tag(tag) Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Tag component {component!r} is not in sorted order per PEP 4
- Tag {tag!r} must have exactly three components
- Tag {tag!r} has an invalid interpreter: {interpreter!r}
- 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/62d379c920348f7e.
Report an issue: GitHub.