{"record":{"id":"4122e418bf8d9075","repo":"redis/redis-py","slug":"initial-connection-failed-no-active-database-fou-4122e4","errorCode":null,"errorMessage":"Initial connection failed - no active database found","messagePattern":"Initial connection failed - no active database found","errorType":"exception","errorClass":"NoValidDatabaseException","httpStatus":null,"severity":"critical","filePath":"redis/multidb/client.py","lineNumber":127,"sourceCode":"            self._health_check_interval,\n            self._check_databases_health,\n        )\n\n        is_active_db_found = False\n\n        for database, weight in self._databases:\n            # Set on state changed callback for each circuit.\n            database.circuit.on_state_changed(self._on_circuit_state_change_callback)\n\n            # Set states according to a weights and circuit state\n            if database.circuit.state == CBState.CLOSED and not is_active_db_found:\n                # Directly set the active database during initialization\n                # without recording a geo failover metric\n                self.command_executor._active_database = database\n                is_active_db_found = True\n\n        if not is_active_db_found:\n            raise NoValidDatabaseException(\n                \"Initial connection failed - no active database found\"\n            )\n\n        self.initialized = True\n\n    def get_databases(self) -> Databases:\n        \"\"\"\n        Returns a sorted (by weight) list of all databases.\n        \"\"\"\n        return self._databases\n\n    def set_active_database(self, database: SyncDatabase) -> None:\n        \"\"\"\n        Promote one of the existing databases to become an active.\n        \"\"\"\n        exists = None\n\n        for existing_db, _ in self._databases:","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/multidb/client.py#L109-L145","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nclient = MultiDBClient(config)\nclient.execute_command('GET', 'k')  # initialize() raises\n\n# after\nimport time\nfor attempt in range(30):\n    try:\n        client = MultiDBClient(config)\n        client.initialize()\n        break\n    except NoValidDatabaseException:\n        time.sleep(2)\nelse:\n    raise RuntimeError('Redis fleet never became healthy')","handlingStrategy":"retry","validationCode":"# Pre-flight: confirm at least one endpoint is reachable before constructing the client\nimport socket\nfrom redis.config import DatabaseConfig  # adjust import to your config module\n\ndef any_reachable(configs) -> bool:\n    for c in configs:\n        host, port = getattr(c, 'host', None), getattr(c, 'port', None)\n        if host and port:\n            try:\n                with socket.create_connection((host, port), timeout=2):\n                    return True\n            except OSError:\n                continue\n    return False","typeGuard":"from redis.multidb.client import MultiDBClient\n\ndef has_active_database(client: MultiDBClient) -> bool:\n    \"\"\"True when at least one database circuit is CLOSED.\"\"\"\n    return any(db.circuit.state.name == 'CLOSED' for db, _ in client.get_databases())","tryCatchPattern":"from redis.multidb.exception import NoValidDatabaseException\nimport time\n\nfor attempt in range(30):\n    try:\n        client = MultiDBClient(config)\n        client.initialize()\n        break\n    except NoValidDatabaseException:\n        time.sleep(2)\nelse:\n    raise RuntimeError('no database became healthy in time')","preventionTips":["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."],"tags":["multidb","active-active","health-check","startup","network"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}