{"record":{"id":"5e7ef0622a85ff9f","repo":"aio-libs/aiohttp","slug":"dns-lookup-failed","errorCode":null,"errorMessage":"DNS lookup failed","messagePattern":"DNS lookup failed","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"aiohttp/resolver.py","lineNumber":145,"sourceCode":"                    host,\n                    port=port,\n                    type=socket.SOCK_STREAM,\n                    family=family,\n                    flags=_AI_ADDRCONFIG,\n                )\n            except aiodns.error.DNSError:\n                if not _is_windows_localhost(host):\n                    raise\n                resp = await self._resolver.getaddrinfo(\n                    host,\n                    port=port,\n                    type=socket.SOCK_STREAM,\n                    family=family,\n                    flags=0,\n                )\n        except aiodns.error.DNSError as exc:\n            msg = exc.args[1] if len(exc.args) >= 1 else \"DNS lookup failed\"\n            raise OSError(None, msg) from exc\n        hosts: list[ResolveResult] = []\n        for node in resp.nodes:\n            address: tuple[bytes, int] | tuple[bytes, int, int, int] = node.addr\n            if node.family == socket.AF_INET6:\n                if len(address) > 3 and address[3]:\n                    # This is essential for link-local IPv6 addresses.\n                    # LL IPv6 is a VERY rare case. Strictly speaking, we should use\n                    # getnameinfo() unconditionally, but performance makes sense.\n                    result = await self._resolver.getnameinfo(\n                        (address[0].decode(\"ascii\"), *address[1:]),\n                        _NAME_SOCKET_FLAGS,\n                    )\n                    resolved_host = result.node\n                else:\n                    resolved_host = address[0].decode(\"ascii\")\n                    port = address[1]\n            else:  # IPv4\n                assert node.family == socket.AF_INET","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/resolver.py#L127-L163","documentation":"Raised by AsyncResolver.resolve when an aiodns DNSError occurs during getaddrinfo (or the windows-localhost getaddrinfo fallback). The DNSError is translated into an OSError whose message is taken from the underlying aiodns error; the literal 'DNS lookup failed' is only the fallback when the DNSError carries no args. This surfaces DNS protocol-level failures (NXDOMAIN, SERVFAIL, timeout) to the caller as a standard OSError.","triggerScenarios":"Resolving a non-existent hostname (NXDOMAIN); a DNS server returning SERVFAIL; aiodns timing out on a dead resolver; network partition blocking port 53. The host was not the windows-localhost special case, so the exception propagates.","commonSituations":"Misconfigured resolv.conf; pointing at an internal DNS that lacks the record; transient ISP DNS outage; typo in the hostname; IPv6-only resolver unreachable from an IPv4-only host.","solutions":["Verify the hostname exists: nslookup/dig <host> from the same host.","Check /etc/resolv.conf (or container DNS config) points at a reachable nameserver.","Retry with backoff for transient failures, or configure a fallback resolver (e.g. resolver=AsyncResolver(nameservers=['8.8.8.8']))."],"exampleFix":"# before\nconnector = TCPConnector(resolver=AsyncResolver())\n# resolves bad-host.example -> OSError: DNS lookup failed\n\n# after\ntry:\n    async with session.get('https://bad-host.example') as r:\n        ...\nexcept OSError as e:\n    log.warning('DNS failed for host: %s', e)","handlingStrategy":"retry","validationCode":"import socket\ntry:\n    socket.gethostbyname(host)\nexcept socket.gaierror:\n    raise ValueError(f'hostname does not resolve: {host}')","typeGuard":"import socket\ndef host_resolves(host: str) -> bool:\n    try:\n        socket.gethostbyname(host)\n        return True\n    except socket.gaierror:\n        return False","tryCatchPattern":"for attempt in range(3):\n    try:\n        async with session.get(url) as r:\n            return await r.read()\n    except OSError as e:\n        # OSError covers DNS lookup failures from the resolver\n        last = e\nraise last","preventionTips":["Validate hostnames before issuing requests in long-running services.","Configure nameservers explicitly in restricted networks.","Wrap outbound requests in retry-with-backoff for transient DNS failures."],"tags":["dns","network","resolver","oserror"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}