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
- Reinstall or rebuild Python against OpenSSL (e.g. apt install libssl-dev before pyenv install).
- Use a distribution/binary that ships the ssl module; verify with python -c "import ssl".
- 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
- Run python -c 'import ssl' as an environment sanity check in Dockerfiles and CI.
- Install libssl-dev (or platform equivalent) before building Python from source.
- Gate TLS features behind ssl availability so startup fails with a clear message.
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
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Socket cannot be of type SSLSocket
- 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/c3ff5d2bf2d93df7.
Report an issue: GitHub.