{"id":"0d1569121f845421","repo":"redis/redis-py","slug":"initial-connection-failed-no-active-database-fou","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/asyncio/multidb/client.py","lineNumber":140,"sourceCode":"                self._check_databases_health,\n            )\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    async def set_active_database(self, database: AsyncDatabase) -> 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":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/multidb/client.py#L122-L158","documentation":"Raised by MultiDBClient.initialize() (redis/asyncio/multidb/client.py:140) after the initial health check completes but no database has a CLOSED circuit breaker. The client iterates `self._databases` looking for the first CLOSED database to promote as active; if every database is OPEN (unhealthy), it cannot establish an active connection and aborts startup with NoValidDatabaseException.","triggerScenarios":"Constructing a `MultiDBClient` and calling `await client.initialize()` (or issuing the first command which auto-initializes) when all configured databases are unreachable, misconfigured, or failed their initial health checks. Also reached if the initial health check policy is lenient (ONE_AVAILABLE) but even one healthy DB could not be found.","commonSituations":"All Redis endpoints down or wrong host/port in `DatabaseConfig`; network partition isolating the client from every DB; TLS/auth misconfiguration causing every PING probe to fail; Redis Enterprise cluster not yet bootstrapped; CI running without the docker-compose stack up.","solutions":["Verify each `DatabaseConfig` URL/credentials with a direct `redis-py` PING before constructing MultiDBClient.","Bring up at least one Redis instance the client can reach (e.g. `invoke devenv`).","Check network/TLS: ensure host/port reachable, certificates valid, firewall rules allow egress.","If some DBs are expected to be down at startup, confirm `initial_health_check_policy` is set to `ONE_AVAILABLE` or `MAJORITY_AVAILABLE` in `MultiDbConfig`."],"exampleFix":"# before\nclient = MultiDBClient(MultiDbConfig(databases_config=[\n    DatabaseConfig(from_url='redis://wrong-host:6379/0'),\n]))\nawait client.initialize()  # NoValidDatabaseException\n\n# after\n# verify endpoint first\nimport redis.asyncio as redis\nr = redis.from_url('redis://correct-host:6379/0')\nawait r.ping()\nclient = MultiDBClient(MultiDbConfig(databases_config=[\n    DatabaseConfig(from_url='redis://correct-host:6379/0'),\n]))\nawait client.initialize()","handlingStrategy":"validation","validationCode":"import redis.asyncio as redis\n\nasync def all_endpoints_reachable(urls: list[str]) -> bool:\n    for u in urls:\n        r = redis.from_url(u)\n        try:\n            await r.ping()\n        except Exception:\n            await r.aclose()\n            return False\n        finally:\n            await r.aclose()\n    return True\n\n# call before MultiDBClient(...).initialize()","typeGuard":"from redis.asyncio.multidb.client import MultiDBClient\n\ndef is_multidb(obj) -> bool:\n    return isinstance(obj, MultiDBClient)","tryCatchPattern":"from redis.multidb.exception import NoValidDatabaseException\n\ntry:\n    await client.initialize()\nexcept NoValidDatabaseException:\n    # startup cannot proceed: log, alert, abort or fall back to single-client mode\n    raise","preventionTips":["Pre-flight PING every configured endpoint with a plain redis-py client before constructing MultiDBClient.","Stand up the docker-compose (`invoke devenv`) or equivalent infra before running tests/services.","Treat initialize() as a hard startup gate in process orchestration (systemd/k8s readiness probe)."],"tags":["multidb","initialization","health","failover","circuit-breaker"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}