aio-libs/aiohttp · error · ClientConnectionError
Cannot initialize a TLS-in-TLS connection to host {req.url.h
Error message
Cannot initialize a TLS-in-TLS connection to host {req.url.host!s}:{req.url.port:d} through an underlying connection to an HTTPS proxy {req.proxy!s} ssl:{req.ssl or 'default'} [{type_err!s}] What it means
Raised inside _start_tls_connection() when `start_tls()` raises a TypeError because the underlying asyncio transport does not support being upgraded (the classic TLS-in-TLS limitation). aiohttp's `_warn_about_tls_in_tls` only suppresses the warning for uvloop, aiofastnet, or Python >=3.11; on older asyncio stdlib doing HTTPS-target-through-HTTPS-proxy, start_tls() rejects the transport and aiohttp wraps the TypeError as ClientConnectionError with a descriptive message.
Source
Thrown at aiohttp/connector.py:1480
except ServerFingerprintMismatch:
tls_transport.close()
if not self._cleanup_closed_disabled:
self._cleanup_closed_transports.append(tls_transport)
raise
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
except TypeError as type_err:
# Example cause looks like this:
# TypeError: transport <asyncio.sslproto._SSLProtocolTransport
# object at 0x7f760615e460> is not supported by start_tls()
raise ClientConnectionError(
"Cannot initialize a TLS-in-TLS connection to host "
f"{req.url.host!s}:{req.url.port:d} through an underlying connection "
f"to an HTTPS proxy {req.proxy!s} ssl:{req.ssl or 'default'} "
f"[{type_err!s}]"
) from type_err
else:
if tls_transport is None:
msg = "Failed to start TLS (possibly caused by closing transport)"
raise client_error(req.connection_key, OSError(msg))
tls_proto.connection_made(
tls_transport
) # Kick the state machine of the new TLS protocol
return tls_transport, tls_proto
def _convert_hosts_to_addr_infos(
self, hosts: list[ResolveResult]
) -> list[AddrInfoType]:View on GitHub (pinned to c0ef574e29)
Solutions
- Upgrade to Python 3.11+ where stdlib asyncio supports TLS-in-TLS (bpo-44011).
- Switch the event loop to uvloop (or aiofastnet) which supports TLS-in-TLS on older Python.
- Use an HTTP (`http://`) proxy instead of an HTTPS proxy where possible - that path uses plain TCP then TLS, no nested TLS.
- Apply the documented monkeypatch (see aiohttp proxy docs / discussion #6044) only as a last resort.
Example fix
# before (Python 3.10, default asyncio)
async with session.get('https://target', proxy='https://proxy:443') as r: ...
# after
import uvloop
uvloop.install() # before creating the event loop
# or upgrade to Python 3.11+ Defensive patterns
Strategy: validation
Validate before calling
import sys
def supports_tls_in_tls() -> bool:
return sys.version_info >= (3, 11) Try / catch
from aiohttp import ClientConnectionError
try:
await session.get('https://target', proxy='https://proxy:443')
except ClientConnectionError as e:
if 'TLS-in-TLS' in str(e):
# switch to uvloop, upgrade Python, or use an http:// proxy
...
raise Prevention
- Prefer http:// proxies over https:// proxies when possible.
- On legacy Python, install uvloop before constructing the event loop.
- Detect the configuration at startup and fail fast with a clear message.
When it happens
Trigger: Sending an HTTPS request through an HTTPS (`https://...`) proxy on Python <3.11 using the default asyncio event loop (not uvloop, not aiofastnet). The plain-HTTP-proxy path is unaffected.
Common situations: Corporate HTTPS proxies (`https://proxy:443`) on legacy Python. CI pinned to Python 3.10. Switching from uvloop to default asyncio on an app that used HTTPS proxies.
Related errors
- Cannot connect to host {host}:{port} ssl:{ssl} [{ClassName}:
- Cannot connect to host {host}:{port} ssl:{ssl} [{strerror}]
- {reason}
- ssl should be SSLContext, Fingerprint, or bool, got {ssl!r}
- Session and connector have to use same event loop
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/733b0597730e40df.json.
Report an issue: GitHub.