You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] A stock SecurityConfig returns 500 to every request when Redis is not running #76
SecurityConfig() defaults to enable_redis=True with redis_url="redis://localhost:6379". With nothing listening there, GuardRedisError escapes dispatch and every request — the first and all after
it — gets HTTP 500. redis_fail_open and fail_secure are not consulted on the
initialization path, so neither of the knobs that look like they cover this does.
Steps to reproduce
With nothing listening on the configured Redis port:
enable_redis=True status=500 body='Internal Server Error'
[guard_core.handlers.redis] ERROR - Redis connection failed: Error 61
connecting to 127.0.0.1:6399
Expected behaviour
Either enable_redis=False by default, or a failed connection degrades to
in-memory with a loud warning. Redis is an optional backend everywhere else in
the library; the default configuration should not make it a hard startup
dependency.
Reproduced on guard-core 3.13.0 with fastapi-guard 7.7.0 (the 7.6.0 in your environment line changes nothing here; guard/middleware.py is identical between the two tags).
Confirmed that none of redis_fail_open, fail_secure or lazy_init is consulted on the init path, in any combination: HandlerInitializer.initialize_redis_handlers awaits RedisManager.initialize() unguarded, and the only place that reads redis_fail_open is the pipeline's per-check error handler at request time. This predates 3.13.0 (identical in 3.12.0).
Plan for 3.14.0: catch GuardRedisError at that one choke point. With redis_fail_open=True the middleware degrades to the in-memory backends with an error log and keeps retrying the connection on later requests. With the default it stays fail-closed, but the adapter turns it into a proper 503 instead of an unhandled 500. We are not flipping enable_redis to False: a security library defaulting to fail-closed when its configured backend is missing is the right default; the bug is that it did so as a crash rather than as a decision.
A Redis outage at initialization no longer crashes the app: with redis_fail_open=True guard-core degrades to the in-memory backends for the process lifetime, with redis_fail_open=False (default) it raises GuardRedisError for the adapter to render; fastapi-guard 7.8.0 answers that with 503 and Retry-After (Guard-Core/fastapi-guard#121, releasing next). The eager Redis reads in sus_patterns_handler.initialize_redis and IPInfoManager.initialize are best-effort as well, so a blip after a good connect no longer escapes the degrade.
Activity
rennf93 commentedon Aug 25, 2026
Thanks @RomanPszonka for opening the issue! By @rennf93's directive:
Reproduced on guard-core 3.13.0 with fastapi-guard 7.7.0 (the 7.6.0 in your environment line changes nothing here;
guard/middleware.pyis identical between the two tags).Confirmed that none of
redis_fail_open,fail_secureorlazy_initis consulted on the init path, in any combination:HandlerInitializer.initialize_redis_handlersawaitsRedisManager.initialize()unguarded, and the only place that readsredis_fail_openis the pipeline's per-check error handler at request time. This predates 3.13.0 (identical in 3.12.0).Plan for 3.14.0: catch
GuardRedisErrorat that one choke point. Withredis_fail_open=Truethe middleware degrades to the in-memory backends with an error log and keeps retrying the connection on later requests. With the default it stays fail-closed, but the adapter turns it into a proper 503 instead of an unhandled 500. We are not flippingenable_redistoFalse: a security library defaulting to fail-closed when its configured backend is missing is the right default; the bug is that it did so as a crash rather than as a decision.rennf93 commentedon Aug 26, 2026
Shipped in guard-core 3.14.0 (PyPI), merged in #82 (500d4ef).
A Redis outage at initialization no longer crashes the app: with
redis_fail_open=Trueguard-core degrades to the in-memory backends for the process lifetime, withredis_fail_open=False(default) it raisesGuardRedisErrorfor the adapter to render; fastapi-guard 7.8.0 answers that with 503 andRetry-After(Guard-Core/fastapi-guard#121, releasing next). The eager Redis reads insus_patterns_handler.initialize_redisandIPInfoManager.initializeare best-effort as well, so a blip after a good connect no longer escapes the degrade.