{"id":"83ef0165fa1bed93","repo":"redis/redis-py","slug":"no-database-connections-currently-available-this","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":"error","filePath":"redis/asyncio/multidb/failover.py","lineNumber":118,"sourceCode":"\n    async def execute(self) -> AsyncDatabase:\n        try:\n            database = await 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/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/multidb/failover.py#L100-L126","documentation":"Raised by `DefaultFailoverStrategyExecutor.execute()` (redis/asyncio/multidb/failover.py:118) as TemporaryUnavailableException when the underlying strategy raised NoValidDatabaseException (error 155) but the executor has not yet exhausted `failover_attempts`. It signals a transient condition: circuits are OPEN but may recover, so the caller should retry rather than abort. Once `failover_counter > failover_attempts`, the original NoValidDatabaseException propagates instead.","triggerScenarios":"Issuing any command through MultiDBClient during a window when every database circuit is OPEN and the failover retry budget (`failover_attempts`, default 10) has not been spent. Each attempt is spaced by `failover_delay` (default 12s).","commonSituations":"Brief full outage; all DBs cycling through OPEN→HALF_OPEN→recovery; client traffic hitting the client during the recovery window.","solutions":["Wrap command execution in a retry loop that catches `TemporaryUnavailableException` and retries with bounded backoff.","Raise `failover_attempts` / shorten `failover_delay` in MultiDbConfig to give the client more chances before propagating.","Ensure at least one backend recovers — investigate the upstream outage.","Circuit-break at the application layer and shed load until the client stops raising this."],"exampleFix":"# before\ntry:\n    await client.set('k','v')\nexcept TemporaryUnavailableException:\n    raise  # propagates, caller sees a hard failure\n\n# after\nfrom redis.multidb.exception import TemporaryUnavailableException\nimport asyncio\nfor attempt in range(5):\n    try:\n        await client.set('k','v')\n        break\n    except TemporaryUnavailableException:\n        await asyncio.sleep(1)\nelse:\n    raise RuntimeError('redis still unavailable after retries')","handlingStrategy":"retry","validationCode":"from redis.multidb.circuit import State as CBState\n\ndef likely_temporarily_unavailable(client) -> bool:\n    # all circuits non-CLOSED -> next command may raise TemporaryUnavailableException\n    return not any(db.circuit.state == CBState.CLOSED for db, _ in client.get_databases())","typeGuard":"from redis.multidb.exception import TemporaryUnavailableException\n\ndef is_temporary_unavailable(exc) -> bool:\n    return isinstance(exc, TemporaryUnavailableException)","tryCatchPattern":"from redis.multidb.exception import TemporaryUnavailableException\nimport asyncio\n\nfor attempt in range(5):\n    try:\n        await client.set('k', 'v')\n        break\n    except TemporaryUnavailableException:\n        await asyncio.sleep(backoff(attempt))\nelse:\n    raise RuntimeError('redis unavailable after retries')","preventionTips":["Wrap command execution in bounded retry that catches TemporaryUnavailableException with exponential backoff.","Tune `failover_attempts` and `failover_delay` in MultiDbConfig to the recovery profile of your backends.","Surface this as a backpressure signal (e.g. 503) at the API edge instead of failing the whole request."],"tags":["multidb","failover","retry","transient","circuit-breaker"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}