{"id":"7b7d7da809ff268b","repo":"pypa/pip","slug":"empty-domain","errorCode":null,"errorMessage":"Empty domain","messagePattern":"Empty domain","errorType":"validation","errorClass":"IDNAError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":564,"sourceCode":"        try:\n            s = str(s, \"ascii\")\n        except (UnicodeDecodeError, TypeError) as err:\n            raise IDNAError(\"should pass a unicode string to the function rather than a byte string.\") from err\n    if len(s) > _max_input_length:\n        raise IDNAError(\"Domain too long\")\n    if uts46:\n        s = uts46_remap(s, std3_rules, transitional)\n\n    # Reject inputs that exceed the maximum DNS domain length up-front\n    # to avoid expensive computation on long inputs.\n    if not valid_string_length(s, trailing_dot=True):\n        raise IDNAError(\"Domain too long\")\n\n    trailing_dot = False\n    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 labels[-1] == \"\":\n        del labels[-1]\n        trailing_dot = True\n    for label in labels:\n        s = alabel(label)\n        if s:\n            result.append(s)\n        else:\n            raise IDNAError(\"Empty label\")\n    if trailing_dot:\n        result.append(b\"\")\n    s = b\".\".join(result)\n    if not valid_string_length(s, trailing_dot):\n        raise IDNAError(\"Domain too long\")\n    return s\n\n\ndef decode(","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/idna/core.py#L546-L582","documentation":"Raised by encode() (core.py:564) when splitting the input on label separators yields no labels at all, or only a single empty label — i.e. the input is the empty string (''), a string containing only separators, or collapses to [''] after split. An empty domain has no encodable content.","triggerScenarios":"Calling idna.encode(''), idna.encode('.'), idna.encode('..'), or encode() on a variable that resolved to an empty string (e.g. a missing Host header, an uninitialised config field, or urlsplit(url).hostname returning None converted to '').","commonSituations":"Missing/empty Host headers in HTTP requests, uninitialised config values, env vars not set defaulting to '', URL parsing that yields an empty hostname for a relative URL, or sanitisation that strips everything.","solutions":["Check for a falsy/empty hostname before calling encode() and handle it as an application-level error.","Default to a sane fallback domain or reject the request when the hostname is missing.","Strip then validate: if not domain: raise ValueError('hostname required')."],"exampleFix":"// before\nidna.encode(host or '')           # host is None -> ''\n\n// after\nif not host:\n    raise ValueError('hostname is required')\nidna.encode(host)","handlingStrategy":"validation","validationCode":"def is_non_empty_domain(domain: str) -> bool:\n    return isinstance(domain, str) and domain.strip() != ''\n\nif not is_non_empty_domain(domain):\n    raise ValueError('hostname is required')\nencoded = idna.encode(domain)","typeGuard":"def is_non_empty_str(s) -> bool:\n    return isinstance(s, str) and s != ''","tryCatchPattern":"import idna\n\ntry:\n    encoded = idna.encode(domain)\nexcept idna.IDNAError as err:\n    if 'Empty domain' in str(err):\n        # missing hostname; fall back or reject\n        raise ValueError('hostname is required') from err\n    raise","preventionTips":["Check for falsy/empty hostnames before encoding and handle as an app-level error.","Validate urlsplit(url).hostname is not None for URL inputs.","Default missing Host headers to a sensible fallback or reject the request."],"tags":["idna","domain","empty","input-validation"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}