{"record":{"id":"66e59e1ed4b5fb14","repo":"redis/redis-py","slug":"no-database-connections-currently-available-this-66e59e","errorCode":null,"errorMessage":"No database connections currently available. This is a temporary condition - please retry the operation.","messagePattern":"No database connections currently available\\. This is a temporary condition - please retry the operation\\.","errorType":"exception","errorClass":"TemporaryUnavailableException","httpStatus":null,"severity":"warning","filePath":"redis/multidb/failover.py","lineNumber":118,"sourceCode":"\n    def execute(self) -> SyncDatabase:\n        try:\n            database = self._strategy.database()\n            self._reset()\n            return database\n        except NoValidDatabaseException as e:\n            if self._next_attempt_ts == 0:\n                self._next_attempt_ts = time.time() + self._failover_delay\n                self._failover_counter += 1\n            elif time.time() >= self._next_attempt_ts:\n                self._next_attempt_ts += self._failover_delay\n                self._failover_counter += 1\n\n            if self._failover_counter > self._failover_attempts:\n                self._reset()\n                raise e\n            else:\n                raise TemporaryUnavailableException(\n                    \"No database connections currently available. \"\n                    \"This is a temporary condition - please retry the operation.\"\n                )\n\n    def _reset(self) -> None:\n        self._next_attempt_ts = 0\n        self._failover_counter = 0\n","sourceCodeStart":100,"sourceCodeEnd":126,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/multidb/failover.py#L100-L126","documentation":"Raised as TemporaryUnavailableException by DefaultFailoverStrategyExecutor.execute() (redis/multidb/failover.py:118) when the WeightBasedFailoverStrategy finds every database's circuit breaker in the OPEN state and the internal failover counter has not yet exceeded failover_attempts (default 10). It is intentionally non-fatal: the executor increments a counter and sets a retry deadline (default 12s) and tells the caller to retry. Once the counter exceeds failover_attempts, the original NoValidDatabaseException is raised instead, making this the transient variant of total failure.","triggerScenarios":"Any command issued through the multidb (Active-Active) client whose command_executor calls executor.execute() while ALL configured databases have circuit breakers in CBState.OPEN. Each database trips its breaker (via pybreaker in redis/multidb/circuit.py) after repeated failures, so a multi-region outage, a misconfigured endpoint, or a failure-detector storm leaves zero CLOSED databases and every execute() call returns this exception until a breaker resets or the 10-attempt cap is exceeded.","commonSituations":"All replica regions temporarily unreachable during a network partition; every endpoint misconfigured to the same wrong host/port so all breakers trip on first health-check batch; a failover-detector threshold (redis/multidb/failure_detector.py) set too aggressive causing cascading OPEN breakers under normal latency; startup before any database has passed its initial health check; TLS/auth rotated everywhere so every connection fails identically.","solutions":["Retry the operation with backoff — this exception is documented as temporary and the executor is already pacing retries internally; a caller-side retry loop with jitter is the intended response.","Verify each database endpoint is reachable (host/port/credentials/TLS) and that health checks in redis/multidb/database.py are passing so breakers can transition OPEN -> CLOSED.","Raise failover_attempts / failover_delay on DefaultFailoverStrategyExecutor if your upstream recovery legitimately takes longer than the default 10 attempts / 12s spacing.","If persistent, inspect circuit breaker state and failure_detector config (redis/multidb/failure_detector.py, redis/multidb/config.py) to confirm thresholds are not too sensitive for your latency profile.","Confirm at least one database is configured and healthy before traffic — a multidb client with zero CLOSED databases will always hit this path."],"exampleFix":"// before\ntry {\n    client.set('k', 'v')\n} catch (e) {\n    // any exception aborts the request\n}\n\n// after - retry transient multidb unavailability\nfor attempt in range(5):\n    try:\n        client.set('k', 'v')\n        break\n    except TemporaryUnavailableException:\n        time.sleep(backoff_with_jitter(attempt))","handlingStrategy":"retry","validationCode":"from redis.multidb.circuit import State as CBState\n\ndef has_closed_database(databases):\n    # Run before issuing commands to confirm at least one breaker is CLOSED\n    return any(db.circuit.state == CBState.CLOSED for db in databases)","typeGuard":null,"tryCatchPattern":"from redis.multidb.exception import TemporaryUnavailableException\n\ndef call_with_retry(client, fn, *args, max_retries=5, base_delay=0.2, **kwargs):\n    for attempt in range(max_retries):\n        try:\n            return fn(client, *args, **kwargs)\n        except TemporaryUnavailableException:\n            if attempt == max_retries - 1:\n                raise\n            time.sleep(base_delay * (2 ** attempt) + random.random() * base_delay)\n    # loop exhausted\n    raise TemporaryUnavailableException('exhausted retries')","preventionTips":["Always wrap multidb client operations in a retry-with-jitter loop since TemporaryUnavailableException is designed to be retried.","Configure failover_attempts and failover_delay on DefaultFailoverStrategyExecutor to match your infrastructure's realistic recovery time.","Monitor circuit-breaker state across databases so you catch all-OPEN conditions before they surface as user-facing failures.","Tune failure_detector thresholds (redis/multidb/failure_detector.py) to avoid overly-sensitive breakers tripping under normal latency.","Ensure at least one database passes its initial health check before routing traffic."],"tags":["multidb","failover","circuit-breaker","retry","active-active","transient"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}