{"record":{"id":"48bc01cc13e178d4","repo":"pypa/pip","slug":"empty-label","errorCode":null,"errorMessage":"Empty label","messagePattern":"Empty label","errorType":"exception","errorClass":"IDNAError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":645,"sourceCode":"    result = []\n    labels = s.split(\".\") if strict else _unicode_dots_re.split(s)\n    if not labels or labels == [\"\"]:\n        raise IDNAError(\"Empty domain\")\n    if not labels[-1]:\n        del labels[-1]\n        trailing_dot = True\n    for label in labels:\n        try:\n            u = ulabel(label)\n        except IDNAError:\n            if display and label[:4].lower() == \"xn--\":\n                u = label.lower()\n            else:\n                raise\n        if u:\n            result.append(u)\n        else:\n            raise IDNAError(\"Empty label\")\n    if trailing_dot:\n        result.append(\"\")\n    return \".\".join(result)\n","sourceCodeStart":627,"sourceCodeEnd":649,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/idna/core.py#L627-L649","documentation":"Raised by idna.encode and idna.decode when an individual label within the domain decodes/encodes to an empty string. This happens when the domain contains consecutive label separators (e.g. 'a..b.com') creating a zero-length label, or a leading/trailing dot pattern that yields an empty intermediate label. Each label must be non-empty per IDNA/DNS rules.","triggerScenarios":"Calling idna.encode('example..com') (double dot), idna.encode('.example.com') with strict processing that yields an empty first label, or idna.decode on a Punycode string with empty labels.","commonSituations":"Concatenating domain parts without checking for empty segments; user typos with double dots; malformed data from upstream; string manipulation that leaves empty labels.","solutions":["Sanitize the domain by removing empty labels: host = '.'.join(p for p in host.split('.') if p).","Validate the domain has no consecutive dots before IDNA processing.","Reject input containing leading/trailing/consecutive dots at the validation boundary."],"exampleFix":"# before\nidna.encode('example..com')  # raises Empty label\n\n# after\nhost = '.'.join(label for label in 'example..com'.split('.') if label)\nidna.encode(host)  # 'example.com'","handlingStrategy":"validation","validationCode":"def sanitize_domain(domain: str) -> str:\n    labels = domain.split('.')\n    cleaned = '.'.join(label for label in labels if label)\n    if not cleaned:\n        raise ValueError('Domain has no valid labels')\n    return cleaned","typeGuard":"def has_no_empty_labels(domain: str) -> bool:\n    labels = domain.split('.')\n    return all(label for label in labels) if labels else False","tryCatchPattern":"from idna.core import IDNAError\ntry:\n    result = idna.encode(domain)\nexcept IDNAError:\n    domain = '.'.join(l for l in domain.split('.') if l)\n    result = idna.encode(domain)","preventionTips":["Strip empty labels from domains before IDNA processing.","Reject domains with consecutive dots at input validation.","Sanitize concatenated domain parts by filtering empty strings."],"tags":["idna","dns","validation","malformed-input"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}