redis/redis-py · error · MaxConnectionsError
Too many connections
Error message
Too many connections
What it means
The non-blocking ConnectionPool raises MaxConnectionsError (a ConnectionError subclass) when get_available_connection finds the free list empty and the in-use count has reached max_connections. Unlike BlockingConnectionPool it does not wait. The most common cause is connections not being returned, but it also fires under genuine load spikes.
Solutions
- Increase max_connections to match your real concurrency.
- Ensure every acquired connection is released (use 'async with redis:' or try/finally), and look for leaks via pool metrics.
- Switch to BlockingConnectionPool so callers wait instead of erroring.
- Shorten long-running commands or move pubsub to a dedicated client/pool.
Example fix
# before pool = ConnectionPool(host='redis.local', max_connections=10) # after pool = BlockingConnectionPool(host='redis.local', max_connections=50, timeout=10)
Defensive patterns
Strategy: retry
Validate before calling
if pool.get_connection_count() and all_in_use:
# raise capacity or shed load before calling
... Try / catch
from redis.exceptions import MaxConnectionsError
for attempt in range(retries):
try:
return await client.get(key)
except MaxConnectionsError:
await asyncio.sleep(backoff(attempt))
raise Prevention
- Size max_connections to peak concurrency and release connections promptly.
- Consider BlockingConnectionPool when bursts are expected.
- Monitor in-use vs idle connection counts.
When it happens
Trigger: Every connection is in use (len(_in_use_connections) >= max_connections) and none are idle when the pool is asked for another connection; e.g. concurrency exceeds the cap, a command holds a connection for a long time, or a leak never releases.
Common situations: Long-running commands blocking connections; missing await client.aclose()/release; pubsub or monitor connections counted against the pool; load spikes with a too-small pool.
Related errors
- No connection available.
- "max_connections" must be a positive integer
- Async Redis client does not support class assignment
- Async Redis client does not support class deletion
- Async Redis client does not support class inclusion
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/600f05615dacc0ac.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/connection.py:2847
if is_created:
await record_connection_create_time(
connection_pool=self,
duration_seconds=time.monotonic() - start_time_created,
)
return connection
except BaseException:
await self.release(connection)
raise
def get_available_connection(self):
"""Get a connection from the pool, without making sure it is connected"""
try:
connection = self._available_connections.pop()
except IndexError:
if len(self._in_use_connections) >= self.max_connections:
raise MaxConnectionsError("Too many connections") from None
connection = self.make_connection()
self._in_use_connections.add(connection)
return connection
def get_encoder(self):
"""Return an encoder based on encoding settings"""
kwargs = self.connection_kwargs
return self.encoder_class(
encoding=kwargs.get("encoding", "utf-8"),
encoding_errors=kwargs.get("encoding_errors", "strict"),
decode_responses=kwargs.get("decode_responses", False),
)
def make_connection(self):
"""Create a new connection. Can be overridden by child classes."""
# Note: We don't record IDLE here because async uses a sync make_connection
# but async record_connection_count. The recording is handled in get_connection.
return self.connection_class(**self.connection_kwargs)View on GitHub (pinned to 6a6b581b48)