aio-libs/aiohttp · error · ClientConnectionError

Connector is closed

Error message

Connector is closed

What it means

Raised by TCPConnector._resolve_host() when DNS caching is disabled (`use_dns_cache=False`) and the connector is already closed at the moment a fresh resolver call would be made. Distinct from [85] (which fires after the connection is built) - this one fires earlier, before any DNS lookup, when there is no cache to fall back on.

Source

Thrown at aiohttp/connector.py:1149

                raise InvalidUrlClientError(host, "is not a canonical IPv4 address")
            return [
                {
                    "hostname": host,
                    "host": host,
                    "port": port,
                    "family": self._family,
                    "proto": 0,
                    "flags": 0,
                }
            ]

        if not self._use_dns_cache:
            if traces:
                for trace in traces:
                    await trace.send_dns_resolvehost_start(host)

            if self._closed:
                raise ClientConnectionError("Connector is closed")

            res = await self._resolver.resolve(host, port, family=self._family)

            if traces:
                for trace in traces:
                    await trace.send_dns_resolvehost_end(host)

            return res

        key = (host, port)
        if key in self._cached_hosts and not self._cached_hosts.expired(key):
            # get result early, before any await (#4014)
            result = self._cached_hosts.next_addrs(key)

            if traces:
                for trace in traces:
                    await trace.send_dns_cache_hit(host)
            return result

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Ensure the connector/session lifetime outlives every request that uses it.
  2. Await in-flight requests before calling `await session.close()`.
  3. If you disabled the cache for testing, re-enable it or replace the resolver with a fake so no real lookup is attempted after close.

Example fix

# before
connector = aiohttp.TCPConnector(use_dns_cache=False)
session = aiohttp.ClientSession(connector=connector)
# later, after close():
await session.get(url)  # -> Connector is closed
# after
# keep the session open for the duration of all requests
async with session.get(url) as resp:
    ...
await session.close()
Defensive patterns

Strategy: validation

Validate before calling

def can_resolve(connector) -> bool:
    return not connector.closed

Try / catch

from aiohttp import ClientConnectionError
try:
    await session.get(url)
except ClientConnectionError as e:
    if str(e) == 'Connector is closed':
        # recreate session/connector
        ...
    raise

Prevention

When it happens

Trigger: A connector built with `use_dns_cache=False` (or cleared) has had close() called, then a request tries to resolve a host that is not cached.

Common situations: Application shutdown racing with in-flight requests on a no-cache connector. Tests that disable DNS caching and tear down the connector between calls. Background tasks outliving the session.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/95d2e283c018ceee.json. Report an issue: GitHub.