{"id":"dc5b7180cabbe04f","repo":"pypa/pip","slug":"malformed-a-label-no-punycode-eligible-content-fo","errorCode":null,"errorMessage":"Malformed A-label, no Punycode eligible content found","messagePattern":"Malformed A-label, no Punycode eligible content found","errorType":"validation","errorClass":"IDNAError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":439,"sourceCode":"    :returns: The U-label as a Unicode string.\n    :raises IDNAError: If the label is malformed or fails validation.\n    \"\"\"\n    if len(label) > _max_input_length:\n        raise IDNAError(\"Label too long\")\n    if not isinstance(label, (bytes, bytearray)):\n        try:\n            label_bytes = label.encode(\"ascii\")\n        except UnicodeEncodeError:\n            check_label(label)\n            return label\n    else:\n        label_bytes = bytes(label)\n\n    label_bytes = label_bytes.lower()\n    if label_bytes.startswith(_alabel_prefix):\n        label_bytes = label_bytes[len(_alabel_prefix) :]\n        if not label_bytes:\n            raise IDNAError(\"Malformed A-label, no Punycode eligible content found\")\n        if label_bytes.endswith(b\"-\"):\n            raise IDNAError(\"A-label must not end with a hyphen\")\n    else:\n        check_label(label_bytes)\n        return label_bytes.decode(\"ascii\")\n\n    try:\n        label = label_bytes.decode(\"punycode\")\n    except UnicodeError as err:\n        raise IDNAError(\"Invalid A-label\") from err\n    check_label(label)\n    return label\n\n\ndef uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:\n    \"\"\"Apply the UTS #46 character mapping to a domain string.\n\n    Implements the mapping table from `UTS #46 §4","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/idna/core.py#L421-L457","documentation":"Raised by ulabel() (core.py:439) when the label has the ACE prefix 'xn--' but nothing follows it — i.e. the Punycode payload is empty. There is no codepoint content to decode, so the A-label is structurally malformed. This is a literal 'xn--' with zero characters after the prefix.","triggerScenarios":"Calling idna.ulabel() or idna.decode() with the string 'xn--' (or 'xn--' as a whole label in a domain like 'xn--.example.com'), or with input that has been truncated/malformed so the Punycode portion is empty.","commonSituations":"Hand-edited or templated hostnames where the Punycode suffix was dropped, string-slicing bugs that truncate after 'xn--', copy-paste of a partial IDN, or test fixtures using 'xn--' as a placeholder.","solutions":["Detect and reject the bare 'xn--' label upstream — it is never a valid A-label.","Regenerate the correct A-label from the intended Unicode label using idna.alabel(unicode_label) rather than hand-building 'xn--...'.","If decoding untrusted input, use decode(domain, display=True) so a malformed 'xn--' label is passed through unchanged instead of raising."],"exampleFix":"// before\nidna.ulabel('xn--')  # empty Punycode payload\n\n// after\nidna.ulabel('xn--example-' )     # real Punycode payload\n# or rebuild from the Unicode form:\nidna.alabel('exämple')         # -> b'xn--exmple-cua'","handlingStrategy":"validation","validationCode":"def is_well_formed_alabel(label) -> bool:\n    s = label.decode('ascii') if isinstance(label, (bytes, bytearray)) else label\n    if s.lower().startswith('xn--'):\n        return len(s) > 4  # must have content after the prefix\n    return True\n\nif not is_well_formed_alabel(label):\n    raise ValueError(\"malformed A-label: bare 'xn--'\")","typeGuard":"import re\nACE_RE = re.compile(r'^xn--[A-Za-z0-9-]+[A-Za-z0-9]$', re.IGNORECASE)\n\ndef is_valid_ace_label(s) -> bool:\n    return isinstance(s, str) and bool(ACE_RE.match(s))","tryCatchPattern":"import idna\n\ntry:\n    decoded = idna.ulabel(label)\nexcept idna.IDNAError as err:\n    if 'Malformed A-label' in str(err):\n        # bare 'xn--'; drop or regenerate the label\n        decoded = label  # pass through unchanged\n    else:\n        raise","preventionTips":["Never hand-build 'xn--' strings; always generate A-labels with idna.alabel().","Validate ACE labels against ^xn--<non-empty payload>$ before decode.","Use decode(domain, display=True) for display-only consumers to pass bad labels through."],"tags":["idna","domain","punycode","a-label","malformed"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}