{"id":"84d26d9268c85597","repo":"encode/httpx","slug":"invalid-ipv6-address-host-r","errorCode":null,"errorMessage":"Invalid IPv6 address: {host!r}","messagePattern":"Invalid IPv6 address: (.+?)","errorType":"validation","errorClass":"InvalidURL","httpStatus":null,"severity":"error","filePath":"httpx/_urlparse.py","lineNumber":376,"sourceCode":"        try:\n            ipaddress.IPv4Address(host)\n        except ipaddress.AddressValueError:\n            raise InvalidURL(f\"Invalid IPv4 address: {host!r}\")\n        return host\n\n    elif IPv6_STYLE_HOSTNAME.match(host):\n        # Validate IPv6 hostnames like [...]\n        #\n        # From https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.2\n        #\n        # \"A host identified by an Internet Protocol literal address, version 6\n        # [RFC3513] or later, is distinguished by enclosing the IP literal\n        # within square brackets (\"[\" and \"]\").  This is the only place where\n        # square bracket characters are allowed in the URI syntax.\"\n        try:\n            ipaddress.IPv6Address(host[1:-1])\n        except ipaddress.AddressValueError:\n            raise InvalidURL(f\"Invalid IPv6 address: {host!r}\")\n        return host[1:-1]\n\n    elif host.isascii():\n        # Regular ASCII hostnames\n        #\n        # From https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.2\n        #\n        # reg-name    = *( unreserved / pct-encoded / sub-delims )\n        WHATWG_SAFE = '\"`{}%|\\\\'\n        return quote(host.lower(), safe=SUB_DELIMS + WHATWG_SAFE)\n\n    # IDNA hostnames\n    try:\n        return idna.encode(host.lower()).decode(\"ascii\")\n    except idna.IDNAError:\n        raise InvalidURL(f\"Invalid IDNA hostname: {host!r}\")\n\n","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/encode/httpx/blob/b5addb64f0161ff6bfe94c124ef76f6a1fba5254/httpx/_urlparse.py#L358-L394","documentation":"Raised by encode_host when the host is bracketed ([...]) indicating an IPv6 literal but ipaddress.IPv6Address() rejects the inner text. httpx expects the RFC3986 form '[address]' with a valid IPv6 inside; malformed addresses (bad hex, wrong group count, bad '::' usage) trigger InvalidURL.","triggerScenarios":"httpx.URL('http://[fe80::1zz]/'), httpx.URL(host='[1234::5678::9abc]') (two '::'), or host='[::g]'.","commonSituations":"Hand-typing IPv6 literals; truncating or pasting partial addresses; forgetting that '::' may appear only once; mixing zone identifiers without '%25' encoding.","solutions":["Validate with ipaddress.IPv6Address(host.strip('[]')) before constructing the URL.","Use a single '::' shorthand; expand the address if unsure.","For zone IDs (link-local), percent-encode: 'fe80::1%25eth0' inside the brackets.","Generate IPv6 literals from ipaddress output rather than string concatenation."],"exampleFix":"// before\nurl = httpx.URL(\"http://[fe80::1zz]/\")  # Invalid IPv6 address\n\n// after\nimport ipaddress\nipaddress.IPv6Address(\"fe80::1\")  # validate first\nurl = httpx.URL(\"http://[fe80::1]/\")","handlingStrategy":"validation","validationCode":"import ipaddress\n\ndef safe_ipv6(host: str) -> str:\n    inner = host.strip(\"[]\")\n    ipaddress.IPv6Address(inner)  # raises AddressValueError early\n    return f\"[{inner}]\"\n\nurl = httpx.URL(host=safe_ipv6(user_ipv6))","typeGuard":"import ipaddress\n\ndef is_valid_ipv6(host: str) -> bool:\n    try:\n        ipaddress.IPv6Address(host.strip(\"[]\"))\n        return True\n    except ipaddress.AddressValueError:\n        return False","tryCatchPattern":"from httpx import InvalidURL\n\ntry:\n    url = httpx.URL(f\"http://[{ipv6}]/\")\nexcept InvalidURL as e:\n    if \"Invalid IPv6\" in str(e):\n        raise ValueError(f\"Bad IPv6 literal: {ipv6!r}\") from e\n    raise","preventionTips":["Always wrap IPv6 literals in brackets for URLs.","Use ipaddress.IPv6Address to validate before constructing URLs.","Use at most one '::' in abbreviated addresses."],"tags":["url","ipv6","validation","network"],"analyzedSha":"b5addb64f0161ff6bfe94c124ef76f6a1fba5254","analyzedAt":"2026-08-04T19:32:56.768Z","schemaVersion":2}