redis/redis-py · critical · NoValidDatabaseException
Initial connection failed - no active database found
Error message
Initial connection failed - no active database found
What it means
Raised as NoValidDatabaseException by MultiDBClient.initialize() (client.py:127) after the initial health check runs and no database ends up with a CLOSED circuit breaker. The client iterates self._databases looking for at least one CLOSED circuit to promote to active; if none qualifies, it cannot route any command and aborts startup.
Solutions
- Verify each configured database endpoint is reachable (redis-cli PING) and credentials/TLS are correct.
- Wait for Redis to be healthy before constructing the client (readiness probe / retry on NoValidDatabaseException).
- Loosen the initial_health_check_policy to ONE_AVAILABLE if business logic tolerates a partially-available fleet.
- Check that config.databases() returns the expected DatabaseConfig entries.
Example fix
# before
client = MultiDBClient(config)
client.execute_command('GET', 'k') # initialize() raises
# after
import time
for attempt in range(30):
try:
client = MultiDBClient(config)
client.initialize()
break
except NoValidDatabaseException:
time.sleep(2)
else:
raise RuntimeError('Redis fleet never became healthy') Defensive patterns
Strategy: retry
Validate before calling
# Pre-flight: confirm at least one endpoint is reachable before constructing the client
import socket
from redis.config import DatabaseConfig # adjust import to your config module
def any_reachable(configs) -> bool:
for c in configs:
host, port = getattr(c, 'host', None), getattr(c, 'port', None)
if host and port:
try:
with socket.create_connection((host, port), timeout=2):
return True
except OSError:
continue
return False Type guard
from redis.multidb.client import MultiDBClient
def has_active_database(client: MultiDBClient) -> bool:
"""True when at least one database circuit is CLOSED."""
return any(db.circuit.state.name == 'CLOSED' for db, _ in client.get_databases()) Try / catch
from redis.multidb.exception import NoValidDatabaseException
import time
for attempt in range(30):
try:
client = MultiDBClient(config)
client.initialize()
break
except NoValidDatabaseException:
time.sleep(2)
else:
raise RuntimeError('no database became healthy in time') Prevention
- Gate MultiDBClient construction behind a readiness check for the Redis fleet.
- Use ONE_AVAILABLE policy when partial availability is acceptable.
- Validate host/port/auth in every DatabaseConfig before boot.
When it happens
Trigger: Constructing MultiDBClient(config) where every configured database fails its initial health check (network unreachable, auth failed, wrong host/port); all circuits transition to OPEN during _perform_initial_health_check; an empty databases list.
Common situations: All Redis endpoints down or misconfigured at app boot; wrong host/port in DatabaseConfig; network partition blocking every endpoint; credentials/TLS misconfigured across the board; CI starting the client before Redis containers are ready.
Related errors
- Initial health check failed. Initial health check policy
- Cannot set active database, database is unhealthy
- Could not find a matching bdb
- Unhealthy database
- Bad response from PING health check
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/4122e418bf8d9075.
Report an issue: GitHub.
Appendix: source
Thrown at redis/multidb/client.py:127
self._health_check_interval,
self._check_databases_health,
)
is_active_db_found = False
for database, weight in self._databases:
# Set on state changed callback for each circuit.
database.circuit.on_state_changed(self._on_circuit_state_change_callback)
# Set states according to a weights and circuit state
if database.circuit.state == CBState.CLOSED and not is_active_db_found:
# Directly set the active database during initialization
# without recording a geo failover metric
self.command_executor._active_database = database
is_active_db_found = True
if not is_active_db_found:
raise NoValidDatabaseException(
"Initial connection failed - no active database found"
)
self.initialized = True
def get_databases(self) -> Databases:
"""
Returns a sorted (by weight) list of all databases.
"""
return self._databases
def set_active_database(self, database: SyncDatabase) -> None:
"""
Promote one of the existing databases to become an active.
"""
exists = None
for existing_db, _ in self._databases:View on GitHub (pinned to 6a6b581b48)