redis/redis-py · warning · NoValidDatabaseException
Cannot set active database, database is unhealthy
Error message
Cannot set active database, database is unhealthy
What it means
Raised as NoValidDatabaseException by MultiDBClient.set_active_database() (client.py:163) when the supplied database IS a member of the list but its circuit breaker is not CLOSED after a fresh _check_db_health run. A non-CLOSED circuit (OPEN or HALF_OPEN) means the database is currently considered unhealthy, so it cannot be promoted to active.
Source
Thrown at redis/multidb/client.py:163
for existing_db, _ in self._databases:
if existing_db == database:
exists = True
break
if not exists:
raise ValueError("Given database is not a member of database list")
self._bg_scheduler.run_coro_sync(self._check_db_health, database)
if database.circuit.state == CBState.CLOSED:
highest_weighted_db, _ = self._databases.get_top_n(1)[0]
self.command_executor.active_database = (
database,
GeoFailoverReason.MANUAL,
)
return
raise NoValidDatabaseException(
"Cannot set active database, database is unhealthy"
)
def add_database(
self, config: DatabaseConfig, skip_initial_health_check: bool = True
):
"""
Adds a new database to the database list.
Args:
config: DatabaseConfig object that contains the database configuration.
skip_initial_health_check: If True, adds the database even if it is unhealthy.
"""
# The retry object is not used in the lower level clients, so we can safely remove it.
# We rely on command_retry in terms of global retries.
config.client_kwargs["retry"] = Retry(retries=0, backoff=NoBackoff())
# Maintenance notifications are disabled by default in underlying clients,View on GitHub (pinned to 6a6b581b48)
Solutions
- Wait for the database to recover (circuit returns to CLOSED via HALF_OPEN retry) before promoting it.
- Verify connectivity to that endpoint independently (PING) and review health-check thresholds.
- Tune the circuit-breaker / health-check settings so transient failures don't keep it OPEN.
- Catch NoValidDatabaseException and retry promotion after a short delay.
Example fix
# before
client.set_active_database(target) # raises — target circuit OPEN
# after
import time
for _ in range(10):
try:
client.set_active_database(target)
break
except NoValidDatabaseException:
time.sleep(2)
else:
raise RuntimeError('target database never recovered') Defensive patterns
Strategy: retry
Validate before calling
# Validate circuit state before promoting
from redis.multidb.circuit import State as CBState
if database.circuit.state != CBState.CLOSED:
raise RuntimeError('target database circuit is not CLOSED; not healthy')
client.set_active_database(database) Type guard
from redis.multidb.circuit import State as CBState
def is_healthy(database) -> bool:
return database.circuit.state == CBState.CLOSED Try / catch
from redis.multidb.exception import NoValidDatabaseException
import time
for _ in range(10):
try:
client.set_active_database(database)
break
except NoValidDatabaseException:
time.sleep(2)
else:
raise RuntimeError('target database never recovered') Prevention
- Promote only databases whose circuit is CLOSED.
- Tune circuit-breaker recovery so transients don't lock promotion out.
- Verify endpoint health independently before failing over.
When it happens
Trigger: Calling set_active_database(db) where db's circuit opened due to recent failures; the on-demand health check at client.py:153 flipping the circuit to OPEN; the database being in HALF_OPEN recovery.
Common situations: Manually failing over to a database that has not recovered yet; network blips causing the circuit to open; aggressive circuit-breaker thresholds marking a slow-but-alive database unhealthy.
Related errors
- Initial connection failed - no active database found
- Cannot set active database, database is unhealthy
- No valid database available for communication
- No valid database available for communication
- No database connections currently available. This is a tempo
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/4cd01e8efbb28c01.
Report an issue: GitHub.