redis/redis-py · error · RedisError
Invalid SSL Certificate Requirements Flag
Error message
Invalid SSL Certificate Requirements Flag: {cert_reqs} What it means
Raised as RedisError inside RedisSSLContext.__init__ when ssl_cert_reqs is passed as a string that is not one of 'none', 'optional', or 'required' (case-sensitive lowercase keys). The mapping is fixed; any other string value aborts context construction before the SSLContext is created.
Solutions
- Use one of the exact lowercase strings: 'none', 'optional', or 'required'.
- Or pass the ssl module constant directly: ssl_cert_reqs=ssl.CERT_REQUIRED.
- Double-check the value when it comes from env/config: normalize to lowercase before passing.
Example fix
// before r = redis.asyncio.Redis(host=h, ssl=True, ssl_cert_reqs='CERT_REQUIRED') // after import ssl r = redis.asyncio.Redis(host=h, ssl=True, ssl_cert_reqs='required') # or ssl.CERT_REQUIRED
Defensive patterns
Strategy: validation
Validate before calling
import ssl
_VALID = {'none': ssl.CERT_NONE, 'optional': ssl.CERT_OPTIONAL, 'required': ssl.CERT_REQUIRED}
def normalize_cert_reqs(v: str) -> str:
if isinstance(v, str) and v.lower() in _VALID:
return v.lower()
raise ValueError(f"cert_reqs must be one of {sorted(_VALID)}") Type guard
from redis.exceptions import RedisError
def is_bad_cert_reqs(exc: BaseException) -> bool:
return isinstance(exc, RedisError) and 'Certificate Requirements Flag' in str(exc) Try / catch
from redis.exceptions import RedisError
for candidate in ('required', ssl.CERT_REQUIRED):
try:
r = redis.asyncio.Redis(host=h, ssl=True, ssl_cert_reqs=candidate)
break
except RedisError as e:
if 'Certificate Requirements Flag' not in str(e):
raise Prevention
- Use exact lowercase 'none'|'optional'|'required' or pass the ssl constant.
- Normalize config values to lowercase before passing.
- Unit-test SSL config with each code path.
When it happens
Trigger: Passing ssl_cert_reqs='CERT_REQUIRED', 'Required', 'yes', '1', or any non-canonical token. Common via from_url with ssl_cert_reqs=<wrong> in the query string, or by passing the ssl module constant's string repr.
Common situations: Confusing ssl.CERT_REQUIRED (int 2) with the string 'CERT_REQUIRED'; copy-pasting a config that used the enum name instead of the library's lowercase keyword; typos; case mismatch ('Required' vs 'required').
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Invalid ssl verify flag
- Invalid value for ' ' in connection URL.
- Maintenance notifications are not supported for connection…
- Maintenance notifications are not supported for connections…
- Maintenance notifications are not supported for Unix domain…
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/9691f4d600d4ba86.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/connection.py:1641
min_version: Optional[TLSVersion] = None,
ciphers: Optional[str] = None,
password: Optional[str] = None,
):
if not SSL_AVAILABLE:
raise RedisError("Python wasn't built with SSL support")
self.keyfile = keyfile
self.certfile = certfile
if cert_reqs is None:
cert_reqs = ssl.CERT_NONE
elif isinstance(cert_reqs, str):
CERT_REQS = { # noqa: N806
"none": ssl.CERT_NONE,
"optional": ssl.CERT_OPTIONAL,
"required": ssl.CERT_REQUIRED,
}
if cert_reqs not in CERT_REQS:
raise RedisError(
f"Invalid SSL Certificate Requirements Flag: {cert_reqs}"
)
cert_reqs = CERT_REQS[cert_reqs]
self.cert_reqs = cert_reqs
self.include_verify_flags = include_verify_flags
self.exclude_verify_flags = exclude_verify_flags
self.ca_certs = ca_certs
self.ca_data = ca_data
self.ca_path = ca_path
self.check_hostname = (
check_hostname if self.cert_reqs != ssl.CERT_NONE else False
)
self.min_version = min_version
self.ciphers = ciphers
self.password = password
self.context: Optional[SSLContext] = None
def get(self) -> SSLContext:View on GitHub (pinned to 6a6b581b48)