aio-libs/aiohttp · error · ClientConnectionError

Connector is closed

Error message

Connector is closed

What it means

Raised in _resolve_host when use_dns_cache is False and self._closed is True at the moment a DNS resolve is attempted. It is the DNS-path counterpart of error 88: the connector was closed (or is closing) while a request still needs it, so rather than dispatch a resolve against a dead connector aiohttp raises ClientConnectionError immediately.

Solutions

  1. Check `if connector.closed` before each request and rebuild when closed.
  2. Keep one long-lived connector/session instead of opening and closing per cycle.
  3. Await all in-flight requests before closing the connector.
  4. When use_dns_cache=False, prefer creating a fresh connector per logical session.

Example fix

# before
connector = aiohttp.TCPConnector(use_dns_cache=False)
# ... later, after connector.close()
await session.get(url)
# after
if connector.closed:
    connector = aiohttp.TCPConnector(use_dns_cache=False)
    session = aiohttp.ClientSession(connector=connector)
await session.get(url)
Defensive patterns

Strategy: try-catch

Validate before calling

async def resolve_or_rebuild(connector, session, host, port):
    if connector.closed:
        raise aiohttp.ClientConnectionError('Connector is closed; rebuild before retry')
    return await connector._resolve_host(host, port)  # or issue the request instead

Type guard

null

Try / catch

try:
    resp = await session.get(url)
except aiohttp.ClientConnectionError as exc:
    if 'Connector is closed' in str(exc):
        connector = aiohttp.TCPConnector(use_dns_cache=False)
        session = aiohttp.ClientSession(connector=connector)
        resp = await session.get(url)
    else:
        raise

Prevention

When it happens

Trigger: Disabling DNS caching and then issuing a request after connector.close(); a session closed by an `async with` exit that still has a pending request; reconnect logic reusing a closed connector.

Common situations: use_dns_cache=False for low-latency clients combined with aggressive connector recycling; test teardown closing the connector before slow requests finish; microservices that pool connectors but close them on config reload.

Related errors


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

Appendix: 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 d041d4d0fd)