python/cpython · error · TypeError
Socket cannot be of type SSLSocket
Error message
Socket cannot be of type SSLSocket
What it means
_check_ssl_socket is called by asyncio transports/servers (e.g. loop.create_connection and loop.create_server) whenever a pre-made sock is supplied together with an ssl context. asyncio implements TLS itself via ssl protocols and requires a plain socket; passing an already-wrapped ssl.SSLSocket would double-handshake and corrupt the protocol, so it raises TypeError immediately.
Source
Thrown at Lib/asyncio/base_events.py:207
# stop it.
return
futures._get_loop(fut).stop()
if hasattr(socket, 'TCP_NODELAY'):
def _set_nodelay(sock):
if (sock.family in {socket.AF_INET, socket.AF_INET6} and
sock.type == socket.SOCK_STREAM and
sock.proto == socket.IPPROTO_TCP):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
else:
def _set_nodelay(sock):
pass
def _check_ssl_socket(sock):
if ssl is not None and isinstance(sock, ssl.SSLSocket):
raise TypeError("Socket cannot be of type SSLSocket")
class _SendfileFallbackProtocol(protocols.Protocol):
def __init__(self, transp):
if not isinstance(transp, transports._FlowControlMixin):
raise TypeError("transport should be _FlowControlMixin instance")
self._transport = transp
self._proto = transp.get_protocol()
self._should_resume_reading = transp.is_reading()
self._should_resume_writing = transp._protocol_paused
transp.pause_reading()
transp.set_protocol(self)
if self._should_resume_writing:
self._write_ready_fut = self._transport._loop.create_future()
else:
self._write_ready_fut = None
async def drain(self):View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass the raw, unwrapped socket and the SSLContext: loop.create_connection(proto, sock=raw_sock, ssl=sslctx) — asyncio does the handshake asynchronously.
- If the socket is already TLS-wrapped by other code, pass ssl=None and treat the stream as already secure (and avoid blocking wrap_socket in async code).
- In async code, replace sslctx.wrap_socket with asyncio's ssl= parameter or await loop.start_tls(...) for upgrading in place.
Example fix
# before
wrapped = ssl_ctx.wrap_socket(raw_sock, server_hostname='example.com')
reader, writer = await asyncio.open_connection(sock=wrapped, ssl=ssl_ctx)
# TypeError: Socket cannot be of type SSLSocket
# after
reader, writer = await asyncio.open_connection(
sock=raw_sock, ssl=ssl_ctx, server_hostname='example.com') Defensive patterns
Strategy: type-guard
Validate before calling
import socket, ssl
def check_not_ssl_socket(sock):
if isinstance(sock, ssl.SSLSocket):
raise TypeError('pass the raw socket plus ssl=SSLContext to asyncio')
return sock Type guard
import ssl
def is_plain_socket(sock) -> bool:
return not (ssl and isinstance(sock, ssl.SSLSocket)) Try / catch
try:
reader, writer = await asyncio.open_connection(sock=sock, ssl=ctx)
except TypeError as e:
if 'SSLSocket' in str(e):
# unwrap is impossible; fix the caller: pass raw sock + ssl=ctx
raise RuntimeError('do not pre-wrap sockets; pass ssl=SSLContext') from None Prevention
- Never call ssl_ctx.wrap_socket in asyncio code paths; pass ssl=ctx to the asyncio API.
- Type-annotate parameters as socket.socket and assert not SSLSocket at boundaries.
- Use await loop.start_tls(...) when you must upgrade an established plain connection.
When it happens
Trigger: s = sslctx.wrap_socket(raw_sock) followed by await loop.create_connection(proto, sock=s, ssl=sslctx); similarly create_server(..., sock=wrapped) or sock_* helpers handed an SSLSocket. Also occurs when a socket obtained from some library already performs TLS (e.g. a tunnel library) and is then forwarded to asyncio with ssl set.
Common situations: Upgrading plain-socket code to TLS by wrapping the socket manually (the intuitive but wrong approach); libraries that hand out connected SSLSocket objects that are then fed to asyncio; mixing blocking ssl module usage with asyncio's async TLS layer.
Related errors
- data: expecting a bytes-like instance, got {type(data).__nam
- server_hostname is only meaningful with ssl
- You must set server_hostname when using ssl without a host
- ssl_handshake_timeout is only meaningful with ssl
- ssl_shutdown_timeout is only meaningful with ssl
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/bd94d219bd41af40.
Report an issue: GitHub.