aio-libs/aiohttp · error · RuntimeError

Resolver requires aiodns library

Error message

Resolver requires aiodns library

What it means

Raised by AsyncResolver.__init__ when the aiodns package is not importable (the module-level aiodns is None). AsyncResolver delegates DNS lookups to aiodns, so without it the resolver cannot function and fails fast at construction rather than silently falling back. This is a hard dependency for this resolver class only.

Solutions

  1. Install aiodns: pip install aiodns (or pip install 'aiohttp[speedups]').
  2. Pin a working aiodns/pycares version if the import fails at runtime despite being installed.
  3. If you cannot add aiodns, use the default ThreadedResolver (omit resolver=) which uses the stdlib socket module.

Example fix

# before
resolver = aiohttp.AsyncResolver()  # RuntimeError: requires aiodns

# after (shell)
# pip install aiodns
resolver = aiohttp.AsyncResolver()
Defensive patterns

Strategy: validation

Validate before calling

import importlib.util
if importlib.util.find_spec('aiodns') is None:
    resolver = None  # use default ThreadedResolver
else:
    resolver = aiohttp.AsyncResolver()

Type guard

import importlib.util
def aiodns_available() -> bool:
    return importlib.util.find_spec('aiodns') is not None

Try / catch

try:
    resolver = aiohttp.AsyncResolver()
except RuntimeError:
    resolver = None  # fall back to default resolver

Prevention

When it happens

Trigger: Constructing aiohttp.AsyncResolver() (or passing connector=TCPConnector(resolver=AsyncResolver())) in an environment where aiodns is not installed or failed to import.

Common situations: Deploying to a fresh container/venv that installed aiohttp but not aiodns; CI matrix that omits the extras (pip install aiohttp without [speedups] or aiodns); aiodns import failing due to a broken pycares build.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/c81193fbab12af47. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/resolver.py:107

                    port=port,
                    family=family,
                    proto=proto,
                    flags=_NUMERIC_SOCKET_FLAGS,
                )
            )

        return hosts

    async def close(self) -> None:
        pass


class AsyncResolver(AbstractResolver):
    """Use the `aiodns` package to make asynchronous DNS lookups"""

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        if aiodns is None:
            raise RuntimeError("Resolver requires aiodns library")

        self._loop = asyncio.get_running_loop()
        self._manager: _DNSResolverManager | None = None
        # If custom args are provided, create a dedicated resolver instance
        # This means each AsyncResolver with custom args gets its own
        # aiodns.DNSResolver instance
        if args or kwargs:
            self._resolver = aiodns.DNSResolver(*args, **kwargs)
            return
        # Use the shared resolver from the manager for default arguments
        self._manager = _DNSResolverManager()
        self._resolver = self._manager.get_resolver(self, self._loop)

    async def resolve(
        self, host: str, port: int = 0, family: socket.AddressFamily = socket.AF_INET
    ) -> list[ResolveResult]:
        try:
            try:

View on GitHub (pinned to d041d4d0fd)