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
- Increase max_connections on the BlockingConnectionPool.
- Increase the pool timeout to tolerate transient stalls.
- Find and fix long-running or leaked commands holding connections.
- 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
- Size max_connections to peak concurrency.
- Keep long-blocking commands on a separate pool.
- Tune timeout to your tolerance; bound fan-out with a Semaphore.
- Investigate leaked or slow commands.
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
- Too many connections
- Cannot disable maintenance notifications after enabling them
- Either maint_notifications_pool_handler or oss_cluster_maint
- "max_connections" must be a positive integer
- Connection has data
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/654de1f0e10e3b3f.json.
Report an issue: GitHub.