{"record":{"id":"ac03320e929aff6a","repo":"pypa/pip","slug":"compressed-tag-set-would-generate-tag-count-tags","errorCode":null,"errorMessage":"Compressed tag set would generate {tag_count} tags, exceeding limit {limit}","messagePattern":"Compressed tag set would generate (.+?) tags, exceeding limit (.+?)","errorType":"validation","errorClass":"TooManyTagsError","httpStatus":null,"severity":"warning","filePath":"src/pip/_vendor/packaging/tags.py","lineNumber":293,"sourceCode":"        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\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","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/tags.py#L275-L311","documentation":"Raised as TooManyTagsError (ValueError subclass) by parse_tag (tags.py:292-296) when limit is not None and the product of the sizes of all components (interpreters x abis x platforms) exceeds limit. This is a DoS-guard preventing a single compressed tag string from exploding into an enormous tag set (e.g. a tag with many alternatives in each field).","triggerScenarios":"parse_tag('a.b.c.d-x.y.z-p.q.r', limit=10) where the product 4*3*2=24 > 10; parsing an adversarial or auto-generated compressed tag with many alternatives under a tight budget.","commonSituations":"A wheel resolver enforcing a tag-expansion budget to avoid quadratic blowups; processing untrusted/index-sourced tag strings; a generator that creates overly-broad compatibility tags.","solutions":["Raise the limit to accommodate the expected tag count, or pass limit=None if you trust the source.","Reduce the breadth of the compressed tag (fewer alternatives per component) so the product stays within budget.","Catch TooManyTagsError and either skip the tag or report it as too broad to handle.","Compute the expected product (prod(len(c.split('.')) for c in tag.split('-'))) before parsing to fail fast with your own message."],"exampleFix":"# before\nparse_tag('a.b.c.d-x.y.z-p.q.r', limit=10)  # TooManyTagsError: 24 > 10\n\n# after - size the limit to the actual product, or trust source\nfrom math import prod\ncount = prod(len(c.split('.')) for c in tag.split('-'))\nparse_tag(tag, limit=count if count <= BUDGET else None)","handlingStrategy":"validation","validationCode":"from math import prod\ndef expected_count(tag: str) -> int:\n    return prod(len(c.split('.')) for c in tag.split('-'))\n\ndef within_budget(tag: str, limit: int) -> bool:\n    return expected_count(tag) <= limit","typeGuard":null,"tryCatchPattern":"from packaging.tags import TooManyTagsError\ntry:\n    parse_tag(tag, limit=BUDGET)\nexcept TooManyTagsError:\n    skip_or_warn(tag)","preventionTips":["Compute the expansion product before parsing to fail fast.","Raise the limit or pass None for trusted sources.","Narrow overly-broad compressed tags before processing."],"tags":["packaging","tags","dos-guard","validation","performance"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}