pypa/pip · error · IDNAError

Domain too long

Error message

Domain too long

What it means

Raised by idna.encode and idna.decode when the input domain string exceeds the maximum allowed length. The check has two layers: a fast guard at _max_input_length (1024 chars) to reject absurdly long strings early, and a standards-based check via valid_string_length enforcing RFC 1035's 253-octet (254 with trailing dot) DNS limit. Domains exceeding these limits cannot be valid DNS names.

Solutions

  1. Validate the hostname length before calling encode/decode: reject if len(host) > 253.
  2. Ensure you are passing only the hostname, not the full URL path or query string.
  3. Truncate or reject oversized input at the data-entry boundary.
  4. Use urllib.parse.urlsplit to extract just the hostname before IDNA processing.

Example fix

# before
idna.encode('a' * 300 + '.example.com')  # raises Domain too long

# after
host = 'a' * 300 + '.example.com'
if len(host) > 253:
    raise ValueError(f'Hostname too long: {len(host)} > 253')
idna.encode(host)
Defensive patterns

Strategy: validation

Validate before calling

MAX_DNS_LENGTH = 253

def is_valid_domain_length(domain: str) -> bool:
    trailing = domain.endswith('.')
    effective = domain.rstrip('.') if trailing else domain
    max_len = 254 if trailing else 253
    return len(effective) <= max_len and len(domain) <= 1024

Type guard

def is_valid_domain_length(domain: str) -> bool:
    return 0 < len(domain) <= 253 or (0 < len(domain) <= 254 and domain.endswith('.'))

Try / catch

from idna.core import IDNAError
try:
    result = idna.encode(domain)
except IDNAError as e:
    if 'too long' in str(e).lower():
        raise ValueError(f'Domain exceeds DNS length limit: {len(domain)}')
    raise

Prevention

When it happens

Trigger: Calling idna.encode() or idna.decode() with a string longer than 253 octets (or 254 with trailing dot), or longer than 1024 characters. Also raised after UTS#46 remapping if the result exceeds limits.

Common situations: User-supplied or generated domain strings that are unbounded; accidentally passing a full URL or path instead of just the hostname; concatenated subdomains; test data with very long random strings.

Related errors


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

Appendix: source

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

        rendered as Unicode. Matches the per-label recovery prescribed
        by UTS #46 §4 and the WHATWG URL "domain to Unicode" algorithm.
    :returns: The decoded domain as a Unicode string.
    :raises IDNAError: If the input is not valid ASCII, contains an
        invalid label, or is empty.
    """
    if not isinstance(s, str):
        try:
            s = str(s, "ascii")
        except (UnicodeDecodeError, TypeError) as err:
            raise IDNAError("Invalid ASCII in A-label") from err
    if len(s) > _max_input_length:
        raise IDNAError("Domain too long")
    if uts46:
        s = uts46_remap(s, std3_rules, False)
    # Reject inputs that exceed the maximum DNS domain length up-front
    # to avoid expensive computation on long inputs.
    if not valid_string_length(s, trailing_dot=True):
        raise IDNAError("Domain too long")
    trailing_dot = False
    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)

View on GitHub (pinned to f399c37189)