pypa/pip · error · IDNAError

Empty label

Error message

Empty label

What it means

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.

Solutions

  1. Sanitize the domain by removing empty labels: host = '.'.join(p for p in host.split('.') if p).
  2. Validate the domain has no consecutive dots before IDNA processing.
  3. Reject input containing leading/trailing/consecutive dots at the validation boundary.

Example fix

# before
idna.encode('example..com')  # raises Empty label

# after
host = '.'.join(label for label in 'example..com'.split('.') if label)
idna.encode(host)  # 'example.com'
Defensive patterns

Strategy: validation

Validate before calling

def sanitize_domain(domain: str) -> str:
    labels = domain.split('.')
    cleaned = '.'.join(label for label in labels if label)
    if not cleaned:
        raise ValueError('Domain has no valid labels')
    return cleaned

Type guard

def has_no_empty_labels(domain: str) -> bool:
    labels = domain.split('.')
    return all(label for label in labels) if labels else False

Try / catch

from idna.core import IDNAError
try:
    result = idna.encode(domain)
except IDNAError:
    domain = '.'.join(l for l in domain.split('.') if l)
    result = idna.encode(domain)

Prevention

When it happens

Trigger: 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.

Common situations: Concatenating domain parts without checking for empty segments; user typos with double dots; malformed data from upstream; string manipulation that leaves empty labels.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/48bc01cc13e178d4. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_vendor/idna/core.py:645

    result = []
    labels = s.split(".") if strict else _unicode_dots_re.split(s)
    if not labels or labels == [""]:
        raise IDNAError("Empty domain")
    if not labels[-1]:
        del labels[-1]
        trailing_dot = True
    for label in labels:
        try:
            u = ulabel(label)
        except IDNAError:
            if display and label[:4].lower() == "xn--":
                u = label.lower()
            else:
                raise
        if u:
            result.append(u)
        else:
            raise IDNAError("Empty label")
    if trailing_dot:
        result.append("")
    return ".".join(result)

View on GitHub (pinned to f399c37189)