python/cpython · critical · RuntimeError

Python ssl module is not available

Error message

Python ssl module is not available

What it means

A RuntimeError raised by loop.start_tls() when the interpreter was built without a working ssl module (asyncio's optional ssl import is None). start_tls exists purely to negotiate TLS, so with no ssl module it cannot proceed and reports unavailability rather than crashing deeper in the stack.

Source

Thrown at Lib/asyncio/base_events.py:1340

                await proto.drain()
                total_sent += read
        finally:
            if total_sent > 0 and hasattr(file, 'seek'):
                file.seek(offset + total_sent)
            await proto.restore()

    async def start_tls(self, transport, protocol, sslcontext, *,
                        server_side=False,
                        server_hostname=None,
                        ssl_handshake_timeout=None,
                        ssl_shutdown_timeout=None):
        """Upgrade transport to TLS.

        Return a new transport that *protocol* should start using
        immediately.
        """
        if ssl is None:
            raise RuntimeError('Python ssl module is not available')

        if not isinstance(sslcontext, ssl.SSLContext):
            raise TypeError(
                f'sslcontext is expected to be an instance of ssl.SSLContext, '
                f'got {sslcontext!r}')

        if not getattr(transport, '_start_tls_compatible', False):
            raise TypeError(
                f'transport {transport!r} is not supported by start_tls()')

        waiter = self.create_future()
        ssl_protocol = sslproto.SSLProtocol(
            self, protocol, sslcontext, waiter,
            server_side, server_hostname,
            ssl_handshake_timeout=ssl_handshake_timeout,
            ssl_shutdown_timeout=ssl_shutdown_timeout,
            call_connection_made=False)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Reinstall or rebuild Python against OpenSSL (e.g. apt install libssl-dev before pyenv install).
  2. Use a distribution/binary that ships the ssl module; verify with python -c "import ssl".
  3. Gate TLS code paths on ssl availability so non-TLS operation still works.

Example fix

# before
transport = await loop.start_tls(raw_tp, proto, ctx)  # RuntimeError

# after
import sys
if 'ssl' not in sys.modules or sys.modules.get('ssl') is None:
    raise RuntimeError('TLS unavailable: this Python lacks the ssl module')
transport = await loop.start_tls(raw_tp, proto, ctx)
Defensive patterns

Strategy: validation

Validate before calling

try:
    import ssl
except ImportError:
    raise RuntimeError('TLS unavailable: Python built without the ssl module')

Try / catch

try:
    tp = await loop.start_tls(raw_tp, proto, ctx)
except RuntimeError as e:
    if 'ssl module is not available' not in str(e):
        raise
    raise RuntimeError('rebuild Python with OpenSSL support') from e

Prevention

When it happens

Trigger: Calling await loop.start_tls(transport, protocol, ctx) on a Python built with the ssl extension disabled (misconfigured build, --without-ssl, or a platform where OpenSSL dev headers were missing at build time).

Common situations: Minimal/stripped Python builds in tiny containers or embedded distributions; distro Pythons compiled without OpenSSL linkage; CI images that trimmed development libraries before building Python.

Understand the failure class

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/c3ff5d2bf2d93df7. Report an issue: GitHub.