redis/redis-py · error · ConnectionError

No connection available.

Error message

No connection available.

What it means

Raised as ConnectionError by BlockingConnectionPool.get_connection() when the configured timeout elapses while waiting for a connection to become available. Unlike the non-blocking pool (which raises MaxConnectionsError immediately), BlockingConnectionPool waits on a condition variable; if no connection is released within self.timeout, asyncio.TimeoutError is caught and re-raised as 'No connection available.'

Source

Thrown at redis/asyncio/connection.py:3100

        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 da03cdc7e8)

Solutions

  1. Increase max_connections on the BlockingConnectionPool.
  2. Increase the pool timeout to tolerate transient stalls.
  3. Find and fix long-running or leaked commands holding connections.
  4. Move long-blocking commands (BLPOP, long Lua) to a dedicated client/pool.

Example fix

// before
pool = BlockingConnectionPool(max_connections=10, timeout=1)
// after
pool = BlockingConnectionPool(max_connections=50, timeout=10)
Defensive patterns

Strategy: retry

Validate before calling

def tune_blocking_pool(max_concurrent_tasks, per_task_ms):
    timeout = max(5, per_task_ms / 1000 * max_concurrent_tasks / 100)
    return dict(max_connections=max_concurrent_tasks, timeout=timeout)

pool = BlockingConnectionPool(**tune_blocking_pool(N, D))

Type guard

def will_likely_block(pool, inflight) -> bool:
    return inflight >= pool.max_connections and pool.timeout is not None

Try / catch

from redis.exceptions import ConnectionError
try:
    await redis.get('k')
except ConnectionError as e:
    if 'No connection available' in str(e):
        await asyncio.sleep(backoff)
        await redis.get('k')

Prevention

When it happens

Trigger: Using BlockingConnectionPool with a finite timeout and exhausting all connections for longer than timeout. Fires at connection.py:3099-3100. The caller's command waits, then fails instead of hanging forever.

Common situations: Undersized max_connections combined with long-running or leaked commands; a slow/stalled Redis backing up every connection; blocking operations (BLPOP, long EVAL) tying up connections; timeout set too low for the workload.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/654de1f0e10e3b3f.json. Report an issue: GitHub.