redis/redis-py · error · ConnectionError

No connection available.

Error message

No connection available.

What it means

BlockingConnectionPool.get_connection waits on an asyncio condition up to 'timeout' seconds; if no connection frees up in time it raises ConnectionError('No connection available.') wrapping the asyncio.TimeoutError. With timeout=None the pool blocks forever and this error never fires. It differs from the plain pool's MaxConnectionsError in that it is a wait-timeout, not an immediate capacity rejection.

Solutions

  1. Increase the pool's timeout to match realistic command latency.
  2. Increase max_connections to cover peak concurrency.
  3. Ensure connections are released promptly (try/finally or 'async with').
  4. Catch ConnectionError and retry with backoff.

Example fix

# before
pool = BlockingConnectionPool(host='redis.local', max_connections=10, timeout=2)
# after
pool = BlockingConnectionPool(host='redis.local', max_connections=50, timeout=30)
Defensive patterns

Strategy: retry

Try / catch

from redis.exceptions import ConnectionError
for attempt in range(retries):
    try:
        return await client.get(key)
    except ConnectionError as e:
        if 'No connection available' not in str(e):
            raise
        await asyncio.sleep(backoff(attempt))
raise

Prevention

When it happens

Trigger: Using a BlockingConnectionPool where all connections stay in use longer than the configured timeout (default 20s), so the condition wait_for times out.

Common situations: blocking_timeout too short for the workload; long-running commands; connection leaks where holders never release; deadlock between concurrent commands.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/654de1f0e10e3b3f. Report an issue: GitHub.

Appendix: source

Thrown at redis/asyncio/connection.py:3103

        start_time_acquired = time.monotonic()

        try:
            async with self._condition:
                async with async_timeout(self.timeout):
                    await self._condition.wait_for(self.can_get_connection)
                    async with self._maybe_pool_lock():
                        # Track connection count before to detect if a new connection is created
                        connections_before = len(self._available_connections) + len(
                            self._in_use_connections
                        )
                        start_time_created = time.monotonic()
                        connection = super().get_available_connection()
                        connections_after = len(self._available_connections) + len(
                            self._in_use_connections
                        )
                        is_created = connections_after > connections_before
        except asyncio.TimeoutError as err:
            raise ConnectionError("No connection available.") from err

        # We now perform the connection check outside of the lock.
        try:
            await self.ensure_connection(connection)

            if is_created:
                await record_connection_create_time(
                    connection_pool=self,
                    duration_seconds=time.monotonic() - start_time_created,
                )

            await record_connection_wait_time(
                pool_name=get_pool_name(self),
                duration_seconds=time.monotonic() - start_time_acquired,
            )

            return connection
        except BaseException:

View on GitHub (pinned to 6a6b581b48)