{"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/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/resolver.py#L127-L163","documentation":"Raised by AsyncResolver.resolve after aiodns.error.DNSError occurs during getaddrinfo. aiohttp translates the aiodns exception into OSError(None, msg) where msg is the aiodns error description (or 'DNS lookup failed' as fallback). This surfaces as a network-layer failure on the connector. Common aiodns codes include ARES_ENOTFOUND (no such host) and ARES_ESERVFAIL (server failure).","triggerScenarios":"Calling client.get('http://nonexistent.invalid/') while using AsyncResolver; DNS server unreachable or returning SERVFAIL/REFUSED; the hostname does not resolve (NXDOMAIN); transient DNS outage during request.","commonSituations":"Wrong hostname in config; DNS not ready in a freshly started container (e.g. k8s service not yet registered); restrictive DNS that blocks the domain; flaky upstream resolver; IPv6-only resolution failing under AF_INET family constraint.","solutions":["Verify the hostname resolves: `python -c 'import socket; print(socket.getaddrinfo(\"host\", 80))'`.","Retry transient DNS failures with exponential backoff (treat as retryable OSError).","Switch resolver: TCPConnector(resolver=ThreadedResolver()) to use the OS getaddrinfo path, which may behave differently.","If behind a custom DNS, point aiodns at it: AsyncResolver(nameservers=['10.0.0.53'], timeout=5)."],"exampleFix":"// before\nasync with aiohttp.ClientSession(connector=TCPConnector(resolver=AsyncResolver())) as s:\n    await s.get('http://does-not-exist.invalid/')\n// after\ntry:\n    async with s.get(url) as r:\n        ...\nexcept OSError as e:  # covers DNS lookup failed\n    log.warning('dns failure for %s: %s', url, e)\n    await asyncio.sleep(backoff); retry()","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async def fetch(session, url, attempts=3):\n    for i in range(attempts):\n        try:\n            async with session.get(url) as r:\n                return await r.read()\n        except OSError as e:\n            # 'DNS lookup failed' and friends\n            if i == attempts - 1:\n                raise\n            await asyncio.sleep(2 ** i)","preventionTips":["Treat OSError from resolve as retryable.","Log exc.args[1] to distinguish NXDOMAIN vs SERVFAIL.","Configure aiodns nameservers/timeout explicitly in production."],"tags":["dns","network","resolver","retryable"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}