redis/redis-py · critical · RedisError

Python wasn't built with SSL support

Error message

Python wasn't built with SSL support

What it means

Raised by SSLConnection.__init__ (connection.py:2118) when the module-level flag SSL_AVAILABLE is False. SSL_AVAILABLE is set in redis/utils.py:30-35 based on whether `import ssl` succeeds at interpreter startup. This is a build-time property of the Python interpreter itself, not a missing redis-py dependency — it means the running Python was compiled/linked without OpenSSL.

Source

Thrown at redis/connection.py:2118

            ssl_exclude_verify_flags: A list of flags to be excluded from the SSLContext.verify_flags. Defaults to None.
            ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None.
            ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates.
            ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to True.
            ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None.
            ssl_password: Password for unlocking an encrypted private key. Defaults to None.

            ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification)
            ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response
            ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert
            ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service.
            ssl_min_version: The lowest supported SSL version. It affects the supported SSL versions of the SSLContext. None leaves the default provided by ssl module.
            ssl_ciphers: A string listing the ciphers that are allowed to be used. Defaults to None, which means that the default ciphers are used. See https://docs.python.org/3/library/ssl.html#ssl.SSLContext.set_ciphers for more information.

        Raises:
            RedisError
        """  # noqa
        if not SSL_AVAILABLE:
            raise RedisError("Python wasn't built with SSL support")

        self.keyfile = ssl_keyfile
        self.certfile = ssl_certfile
        if ssl_cert_reqs is None:
            ssl_cert_reqs = ssl.CERT_NONE
        elif isinstance(ssl_cert_reqs, str):
            CERT_REQS = {  # noqa: N806
                "none": ssl.CERT_NONE,
                "optional": ssl.CERT_OPTIONAL,
                "required": ssl.CERT_REQUIRED,
            }
            if ssl_cert_reqs not in CERT_REQS:
                raise RedisError(
                    f"Invalid SSL Certificate Requirements Flag: {ssl_cert_reqs}"
                )
            ssl_cert_reqs = CERT_REQS[ssl_cert_reqs]
        self.cert_reqs = ssl_cert_reqs
        self.ssl_include_verify_flags = ssl_include_verify_flags

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Reinstall or rebuild Python with SSL support: on Debian/Ubuntu `apt-get install libssl-dev` before compiling; on pyenv ensure build deps are present then `pyenv install <version>`.
  2. Switch to an official CPython distribution or Docker base image that ships with SSL (e.g. python:3.x-slim instead of a hand-rolled scratch build).
  3. Verify with `python -c "import ssl; print(ssl.OPENSSL_VERSION)"` — if it raises ImportError, the interpreter is the problem, not redis-py.
  4. As a temporary workaround, drop TLS and use a plain redis:// connection only if the network path does not require encryption (not recommended for production).

Example fix

# before (fails on SSL-less interpreter)
client = redis.Redis.from_url("rediss://my-host:6379")

# after: rebuild python with ssl, verify, then the same call works
# python -c "import ssl; print(ssl.OPENSSL_VERSION)"
client = redis.Redis.from_url("rediss://my-host:6379")
Defensive patterns

Strategy: validation

Validate before calling

import ssl
try:
    import ssl  # noqa
    SSL_OK = True
except ImportError:
    SSL_OK = False

if not SSL_OK and url.startswith("rediss://"):
    raise RuntimeError("rediss:// requires a Python built with SSL support")

client = redis.Redis.from_url(url) if SSL_OK else None

Type guard

def supports_ssl() -> bool:
    try:
        import ssl  # noqa: F401
        return True
    except ImportError:
        return False

Try / catch

from redis.exceptions import RedisError
try:
    client = redis.Redis.from_url("rediss://host")
    client.ping()
except RedisError as e:
    if "SSL support" in str(e):
        raise SystemExit("Rebuild Python with SSL or use redis://")
    raise

Prevention

When it happens

Trigger: Instantiating SSLConnection directly, or constructing a client with a rediss:// URL (parse_url sets connection_class=SSLConnection at line 2384-2385), or passing ssl=True / connection_class=SSLConnection to Redis()/ConnectionPool(). The check `if not SSL_AVAILABLE` fires in __init__ before any network I/O.

Common situations: Using a custom-compiled or stripped Python (e.g. some slim Docker base images, pyenv builds missing libssl-dev, RHEL-derived images, or Python built from source without proper SSL linkage). Switching a working redis:// app to rediss:// against Redis Cloud / a TLS endpoint and hitting this on a minimal CI image.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/72183205c5581fcb.json. Report an issue: GitHub.