redis/redis-py · error · RedisError

Invalid SSL Certificate Requirements Flag

Error message

Invalid SSL Certificate Requirements Flag: {ssl_cert_reqs}

What it means

Raised in SSLConnection.__init__ when ssl_cert_reqs is passed as a string that is not one of the recognized keys ('none', 'optional', 'required'). The constructor maps those strings to ssl.CERT_NONE / ssl.CERT_OPTIONAL / ssl.CERT_REQUIRED; any other string value is rejected. Passing the ssl constant directly (e.g. ssl.CERT_REQUIRED) bypasses string parsing and never triggers this.

Solutions

  1. Use one of the exact strings 'none', 'optional', or 'required' (case-sensitive).
  2. Pass the ssl constant directly: import ssl; ssl_cert_reqs=ssl.CERT_REQUIRED.
  3. If the value comes from config, validate it against {'none','optional','required'} before constructing the client.

Example fix

# before
r = redis.Redis(ssl_cert_reqs='CERT_REQUIRED')
# after
import ssl
r = redis.Redis(ssl_cert_reqs=ssl.CERT_REQUIRED)
# or
r = redis.Redis(ssl_cert_reqs='required')
Defensive patterns

Strategy: validation

Validate before calling

import ssl

_ALLOWED = {'none': ssl.CERT_NONE, 'optional': ssl.CERT_OPTIONAL, 'required': ssl.CERT_REQUIRED}

def resolve_cert_reqs(value):
    if value is None:
        return ssl.CERT_NONE
    if isinstance(value, str) and value in _ALLOWED:
        return _ALLOWED[value]
    if isinstance(value, int):
        return value
    raise ValueError(f'Invalid ssl_cert_reqs: {value!r}')

r = redis.Redis(ssl_cert_reqs=resolve_cert_reqs(cfg['ssl_cert_reqs']))

Type guard

import ssl

def is_valid_cert_reqs(value) -> bool:
    if value is None:
        return True
    if isinstance(value, int):
        return value in (ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED)
    return isinstance(value, str) and value in ('none', 'optional', 'required')

Try / catch

from redis.exceptions import RedisError
try:
    r = redis.Redis(ssl_cert_reqs=user_value)
except RedisError as e:
    if 'Invalid SSL Certificate Requirements Flag' in str(e):
        user_value = 'required'  # fall back to a safe default
        r = redis.Redis(ssl_cert_reqs=user_value)
    else:
        raise

Prevention

When it happens

Trigger: Calling SSLConnection(..., ssl_cert_reqs='require') (typo) or ssl_cert_reqs='CERT_REQUIRED' (the constant name rather than the keyword). Passing an arbitrary lowercase token not in the allowlist.

Common situations: Confusion between the string keyword ('required') and the ssl module constant name ('CERT_REQUIRED'). Typos in config files or env vars fed into ssl_cert_reqs. Copy-pasting cert-req names from other libraries.

Understand the failure class

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/aae86099ee6a86b6. Report an issue: GitHub.

Appendix: source

Thrown at redis/connection.py:2147

        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
        self.ssl_exclude_verify_flags = ssl_exclude_verify_flags
        self.ca_certs = ssl_ca_certs
        self.ca_data = ssl_ca_data
        self.ca_path = ssl_ca_path
        self.check_hostname = (
            ssl_check_hostname if self.cert_reqs != ssl.CERT_NONE else False
        )
        self.certificate_password = ssl_password
        self.ssl_validate_ocsp = ssl_validate_ocsp
        self.ssl_validate_ocsp_stapled = ssl_validate_ocsp_stapled
        self.ssl_ocsp_context = ssl_ocsp_context
        self.ssl_ocsp_expected_cert = ssl_ocsp_expected_cert
        self.ssl_min_version = ssl_min_version

View on GitHub (pinned to 6a6b581b48)