python/cpython · error · ValueError
ssl_shutdown_timeout is only meaningful with ssl
Error message
ssl_shutdown_timeout is only meaningful with ssl
What it means
Raised by create_connection when ssl_shutdown_timeout is given but ssl is not. This timeout bounds the TLS shutdown (close_notify) phase of the connection; like the handshake timeout it is meaningful only for TLS, so asyncio rejects it on plaintext connections.
Source
Thrown at Lib/asyncio/base_events.py:1110
# already-connected socket was passed or when only a port
# is given. To avoid this error, you can pass
# server_hostname='' -- this will bypass the hostname
# check. (This also means that if host is a numeric
# IP/IPv6 address, we will attempt to verify that exact
# address; this will probably fail, but it is possible to
# create a certificate for a specific IP address, so we
# don't judge it here.)
if not host:
raise ValueError('You must set server_hostname '
'when using ssl without a host')
server_hostname = host
if ssl_handshake_timeout is not None and not ssl:
raise ValueError(
'ssl_handshake_timeout is only meaningful with ssl')
if ssl_shutdown_timeout is not None and not ssl:
raise ValueError(
'ssl_shutdown_timeout is only meaningful with ssl')
if sock is not None:
_check_ssl_socket(sock)
if happy_eyeballs_delay is not None and interleave is None:
# If using happy eyeballs, default to interleave addresses by family
interleave = 1
if host is not None or port is not None:
if sock is not None:
raise ValueError(
'host/port and sock can not be specified at the same time')
infos = await self._ensure_resolved(
(host, port), family=family,
type=socket.SOCK_STREAM, proto=proto, flags=flags, loop=self)
if not infos:View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass ssl_shutdown_timeout only in the branch that also passes ssl=ctx.
- Strip TLS-only keys from kwargs when TLS is disabled: kwargs.pop('ssl_shutdown_timeout', None).
- Keep ssl, server_hostname, and both ssl timeouts as one atomic kwargs group.
Example fix
// before await loop.create_connection(proto, h, p, ssl_shutdown_timeout=5) # no ssl // after await loop.create_connection(proto, h, p, ssl=ctx, ssl_shutdown_timeout=5)
Defensive patterns
Strategy: validation
Validate before calling
tls_kwargs = {}
if ctx is not None:
tls_kwargs.update(ssl=ctx, ssl_shutdown_timeout=5) Try / catch
try:
await loop.create_connection(proto, h, p, ssl_shutdown_timeout=5)
except ValueError:
await loop.create_connection(proto, h, p, ssl=ssl.create_default_context(),
ssl_shutdown_timeout=5) Prevention
- Group ssl_shutdown_timeout with ssl in config validation: reject one without the other.
- When disabling TLS at runtime, clear the whole TLS kwargs block together.
- Add a config schema check that ssl-adjacent keys require ssl=true.
When it happens
Trigger: Calling loop.create_connection(proto, host, port, ssl_shutdown_timeout=5.0) with ssl unset (None). The argument exists only in newer Pythons; combined with conditional TLS it is easy to leak into a plaintext call.
Common situations: Config-driven client builders that forward a TLS settings object as **kwargs and a code path that sets ssl=None; disabling TLS against a local test server while keeping the shutdown timeout setting.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- ssl_handshake_timeout is only meaningful with ssl
- server_hostname is only meaningful with ssl
- You must set server_hostname when using ssl without a host
- sslcontext is expected to be an instance of ssl.SSLContext,
- Socket cannot be of type SSLSocket
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/17e6dc9e8359dcce.
Report an issue: GitHub.