RustPython/RustPython · error · ValueError

ssl_shutdown_timeout is only meaningful with ssl

Error message

ssl_shutdown_timeout is only meaningful with ssl

What it means

ValueError from BaseEventLoop.create_connection: ssl_shutdown_timeout (seconds allowed for the TLS shutdown/close_notify phase, added in Python 3.11+) was supplied while ssl is falsy. Like ssl_handshake_timeout it only applies to the TLS lifecycle, so asyncio rejects it on plaintext connections.

Source

Thrown at Lib/asyncio/base_events.py:1104

            # 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 aaeab4f754)

Solutions

  1. Remove ssl_shutdown_timeout from non-TLS calls
  2. Enable TLS with ssl=<SSLContext> so the shutdown timeout applies
  3. Gate the kwarg: kwargs = {'ssl_shutdown_timeout': 5} if ctx else {}

Example fix

# before
await loop.create_connection(proto, 'example.com', 80,
                                ssl_shutdown_timeout=5.0)

# after
kwargs = {'ssl_shutdown_timeout': 5.0} if ssl_ctx else {}
await loop.create_connection(proto, 'example.com', 80, ssl=ssl_ctx, **kwargs)
Defensive patterns

Strategy: validation

Validate before calling

kwargs = {}
if ssl_ctx is not None:
    kwargs['ssl_shutdown_timeout'] = 5.0
    kwargs['ssl'] = ssl_ctx
await loop.create_connection(proto, host, port, **kwargs)

Prevention

When it happens

Trigger: await loop.create_connection(proto, host, 80, ssl_shutdown_timeout=5.0) with ssl unset; forwarding a full kwargs dict from a TLS-aware client into a plain connection; mixing the new kwarg into calls that never enable ssl.

Common situations: Client libraries parameterizing every TLS option regardless of scheme; test configs that disable ssl but keep timeout settings; code written against 3.11+ kwargs run through a shared helper used for both TLS and non-TLS targets.

Understand the failure class

Related errors


AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17). Data as JSON: /api/errors/3b324f3facfe2234. Report an issue: GitHub.