aio-libs/aiohttp · error · ClientConnectorSSLError

Cannot connect to host {host}:{port} ssl:{ssl} [{strerror}]

Error message

Cannot connect to host {host}:{port} ssl:{ssl} [{strerror}]

What it means

Raised inside _wrap_create_connection() when the TLS handshake raises an `ssl_errors` exception (ssl.SSLError / ssl.SSLError subclasses that are not certificate errors) during a direct connection. Wrapped as ClientConnectorSSLError(req.connection_key, exc). Typically indicates a protocol/cipher mismatch or handshake abort rather than a certificate-trust problem.

Source

Thrown at aiohttp/connector.py:1349

                    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,
        # which is standard TLS and works on all event loops and Python versions.
        if req.proxy is None or req.proxy.scheme != "https":

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Verify the URL scheme matches what the server speaks (`http://` vs `https://`).
  2. Inspect the wrapped OSError via `traceback.print_exc()` for the SSL reason string.
  3. Adjust the SSLContext min/max version and cipher list to what the server supports.
  4. Update the Python/OpenSSL build if the failure is `unsupported protocol`.

Example fix

# before
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.maximum_version = ssl.TLSVersion.TLSv1
# after
ctx = ssl.create_default_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
Defensive patterns

Strategy: try-catch

Validate before calling

import ssl

def modern_tls_context() -> ssl.SSLContext:
    ctx = ssl.create_default_context()
    ctx.minimum_version = ssl.TLSVersion.TLSv1_2
    return ctx

Try / catch

from aiohttp import ClientConnectorSSLError
try:
    await session.get(url, ssl=ctx)
except ClientConnectorSSLError as e:
    # log e.__cause__ for the OpenSSL reason string
    raise

Prevention

When it happens

Trigger: Server supports only outdated TLS versions/ciphers, the SSLContext is misconfigured (e.g. min/max version wrong), the server abruptly closed the socket during handshake, or a non-TLS service answered on port 443.

Common situations: Forcing TLSv1.0 on a TLSv1.3-only server. Restrictive cipher suite on the client. Connecting plain HTTP to an HTTPS URL/port. Middleboxes terminating TLS incorrectly. Old OpenSSL linked into Python.

Related errors


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