aio-libs/aiohttp · error · ClientConnectorCertificateError

Cannot connect to host {host}:{port} ssl:{ssl} [{ClassName}:

Error message

Cannot connect to host {host}:{port} ssl:{ssl} [{ClassName}: {args}]

What it means

Raised inside _wrap_create_connection() when the underlying asyncio create_connection() raises an exception matching `cert_errors` (e.g. ssl.SSLCertVerificationError, ssl.CertificateError) during the initial direct TLS handshake. Wrapped as ClientConnectorCertificateError(req.connection_key, exc), carrying the host/port/SSL config of the failed request.

Source

Thrown at aiohttp/connector.py:1347

            ):
                sock = await aiohappyeyeballs.start_connection(
                    addr_infos=addr_infos,
                    local_addr_infos=self._local_addr_infos,
                    happy_eyeballs_delay=self._happy_eyeballs_delay,
                    interleave=self._interleave,
                    loop=self._loop,
                    socket_factory=self._socket_factory,
                )
                # Add ssl_shutdown_timeout for Python 3.11+ when SSL is used
                if (
                    kwargs.get("ssl")
                    and self._ssl_shutdown_timeout
                    and sys.version_info >= (3, 11)
                ):
                    kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout
                return await create_connection(self._loop, *args, **kwargs, sock=sock)
        except cert_errors as exc:
            raise ClientConnectorCertificateError(req.connection_key, exc) from exc
        except ssl_errors as exc:
            raise ClientConnectorSSLError(req.connection_key, exc) from exc
        except OSError as exc:
            if exc.errno is None and isinstance(exc, asyncio.TimeoutError):
                raise
            raise client_error(req.connection_key, exc) from exc

    def _warn_about_tls_in_tls(
        self,
        underlying_transport: asyncio.Transport,
        req: ClientRequest,
    ) -> None:
        """Issue a warning if the requested URL has HTTPS scheme."""
        if req.url.scheme != "https":
            return

        # TLS-in-TLS only applies when the proxy itself is HTTPS.
        # When the proxy is HTTP, start_tls upgrades a plain TCP connection,

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Install the correct CA bundle (e.g. `certifi`, or your corporate root) into the trust store.
  2. Provide a custom `ssl.SSLContext` with the right CA loaded: `ssl.create_default_context(cafile=...)`.
  3. For dev only, pass `ssl=False` to disable verification (never in production).
  4. Check system time with `date` and fix clock skew.

Example fix

# before
async with session.get('https://self-signed.example') as r: ...
# after (dev only)
import ssl
ctx = ssl.create_default_context(cadata=PEM_CERT)
# or, dev-only bypass:
async with session.get('https://self-signed.example', ssl=False) as r: ...
Defensive patterns

Strategy: try-catch

Validate before calling

import ssl

def trusted_context(cafile=None, cadata=None) -> ssl.SSLContext:
    ctx = ssl.create_default_context(cafile=cafile, cadata=cadata)
    return ctx

Try / catch

from aiohttp import ClientConnectorCertificateError
try:
    await session.get(url, ssl=ctx)
except ClientConnectorCertificateError as e:
    # e.g. install missing CA or pin fingerprint; do not blind-bypass in prod
    raise

Prevention

When it happens

Trigger: Direct (non-proxy) HTTPS connection where the server certificate fails verification: self-signed cert, expired cert, wrong hostname, untrusted CA, or a pinned-fingerprint mismatch during the handshake.

Common situations: Self-signed dev/staging servers. Corporate MITM proxies with an untrusted CA. System clock skew making a valid cert look expired. Missing CA bundle on minimal containers. Hostname mismatch behind a CDN.

Related errors


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