redis/redis-py · critical · NoValidDatabaseException
No valid database available for communication
Error message
No valid database available for communication
What it means
Raised by `WeightBasedFailoverStrategy.database()` (redis/asyncio/multidb/failover.py:66) when iterating `self._databases` yields no database whose circuit breaker is in the CLOSED state. This is the inner strategy signal that failover cannot pick a target; the `DefaultFailoverStrategyExecutor` catches it and either retries or surfaces error 156.
Source
Thrown at redis/asyncio/multidb/failover.py:66
async def execute(self) -> AsyncDatabase:
"""Execute the failover strategy."""
pass
class WeightBasedFailoverStrategy(AsyncFailoverStrategy):
"""
Failover strategy based on database weights.
"""
def __init__(self):
self._databases = WeightedList()
async def database(self) -> AsyncDatabase:
for database, _ in self._databases:
if database.circuit.state == CBState.CLOSED:
return database
raise NoValidDatabaseException("No valid database available for communication")
def set_databases(self, databases: Databases) -> None:
self._databases = databases
class DefaultFailoverStrategyExecutor(FailoverStrategyExecutor):
"""
Executes given failover strategy.
"""
def __init__(
self,
strategy: AsyncFailoverStrategy,
failover_attempts: int = DEFAULT_FAILOVER_ATTEMPTS,
failover_delay: float = DEFAULT_FAILOVER_DELAY,
):
self._strategy = strategy
self._failover_attempts = failover_attemptsView on GitHub (pinned to da03cdc7e8)
Solutions
- Restore at least one Redis endpoint so its circuit recovers to CLOSED (it will be probed in HALF_OPEN after the grace period).
- Increase `grace_period` on the circuit breaker / DB config so circuits move to HALF_OPEN and get re-probed sooner if the backend recovered.
- Tune failure-detector thresholds (`min_num_failures`, `failure_rate_threshold`, `failures_detection_window`) so transient errors do not open every circuit.
- Add more databases (redundant regions) so a single-region outage cannot exhaust the list.
Example fix
# before
# all DBs unreachable -> every circuit OPEN -> NoValidDatabaseException on next command
# after
# 1. bring one endpoint back, then
# 2. tune failover to recover faster
from redis.multidb.circuit import DEFAULT_GRACE_PERIOD
cfg = MultiDbConfig(
databases_config=[db_a, db_b],
)
for db_cfg in cfg.databases_config:
db_cfg.grace_period = DEFAULT_GRACE_PERIOD # shorten to retry HALF_OPEN sooner Defensive patterns
Strategy: retry
Validate before calling
from redis.multidb.circuit import State as CBState
def any_closed(client) -> bool:
return any(db.circuit.state == CBState.CLOSED for db, _ in client.get_databases())
# do not trigger failover/command execution when any_closed(client) is False Type guard
from redis.multidb.circuit import State as CBState
def has_closed_circuit(client) -> bool:
return any(db.circuit.state == CBState.CLOSED for db, _ in client.get_databases()) Try / catch
from redis.multidb.exception import NoValidDatabaseException
import asyncio
for _ in range(10):
try:
await client.set('k', 'v')
break
except NoValidDatabaseException:
await asyncio.sleep(1)
else:
raise Prevention
- Maintain redundant databases across regions/zones so a single outage cannot open every circuit.
- Tune circuit-breaker `grace_period` and failure detector thresholds so circuits recover promptly.
- Application-level circuit breaker: shed load when all DB circuits are OPEN instead of hammering the client.
When it happens
Trigger: The failover strategy being asked (during command execution via `_check_active_database`, or during `set_active_database` fallback) to pick a healthy DB when every database's circuit is OPEN or HALF_OPEN.
Common situations: Total outage of all Redis endpoints; all circuits tripped by the failure detector; the grace period before HALF_OPEN has not elapsed; failure_rate_threshold/min_num_failures too aggressive.
Related errors
- Initial connection failed - no active database found
- Cannot set active database, database is unhealthy
- No database connections currently available. This is a tempo
- Unhealthy database
- Item not found
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/23da74206c09261f.json.
Report an issue: GitHub.