redis/redis-py · error · ConnectionError
Connection not ready
Error message
Connection not ready
What it means
Raised as a ConnectionError by ConnectionPool.get_connection (connection.py:3289-3294) when, after detecting leftover data (error 416 path), the pool disconnects and reconnects the connection but connection.can_read() STILL returns True. This means even a fresh handshake sees unread data — a deeper socket/protocol problem rather than a one-off unread response.
Source
Thrown at redis/connection.py:3294
# a command. if not, the connection was either returned to the
# pool before all data has been read or the socket has been
# closed. either way, reconnect and verify everything is good.
try:
if (
connection.can_read()
and self.cache is None
and not self.maint_notifications_enabled()
):
raise ConnectionError("Connection has data")
except (ConnectionError, TimeoutError, OSError):
connection.disconnect()
connection.connect()
if (
connection.can_read()
and self.cache is None
and not self.maint_notifications_enabled()
):
raise ConnectionError("Connection not ready")
except BaseException:
# release the connection back to the pool so that we don't
# leak it
self.release(connection)
raise
if is_created:
record_connection_create_time(
connection_pool=self,
duration_seconds=time.monotonic() - start_time_created,
)
return connection
def get_encoder(self) -> Encoder:
"Return an encoder based on encoding settings"
kwargs = self.connection_kwargs
return Encoder(View on GitHub (pinned to da03cdc7e8)
Solutions
- If you expect server pushes, enable the appropriate consumer (client-side caching cache_config, maintenance notifications, or a pubsub/keyspace-notifications handler) so pushes are consumed instead of treated as stray data.
- Switch to RESP3 with a proper push handler if the server is sending push messages.
- Investigate intermediaries (proxies, load balancers) that may be injecting data; test with a direct connection.
- As a workaround, recreate the pool; if it recurs, the server is genuinely pushing data the client must handle.
Example fix
# before
client = redis.Redis(connection_pool=pool) # keyspace notifications enabled server-side
# after (consume the pushes via keyspace notifications API)
p = client.pubsub()
p.psubscribe("__keyevent@0__:*")
# drain in a loop, or use client.keyspace_notifications helpers Defensive patterns
Strategy: try-catch
Try / catch
from redis.exceptions import ConnectionError
for _ in range(3):
try:
return client.get("k")
except ConnectionError as e:
if "not ready" in str(e).lower():
# pool will rebuild; back off and retry
time.sleep(0.1)
continue
raise
raise Prevention
- If you expect server pushes, enable a consumer (CSC, keyspace notifications, pubsub) so data is drained.
- Use RESP3 with a configured push handler when the server sends push messages.
- Test for intermediaries/proxies that inject bytes; prefer direct connections for diagnosis.
When it happens
Trigger: A pooled connection that, after disconnect()+connect(), immediately reports data available to read. Can happen with persistent server-side pushes the client isn't consuming, a half-closed socket, or a misbehaving proxy/intermediary that injects bytes after reconnect.
Common situations: Server-side keyspace notifications or push messages arriving on a connection the client isn't set up to consume (and CSC/maint notifications aren't enabled to absorb them); buggy network middleboxes; RESP3 push data on a connection not configured with a push handler.
Related errors
- Connection has data
- protocol must be an integer
- protocol must be either 2 or 3
- Invalid RESP version
- Bad response from PING health check
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/fcf5eff9625f284e.json.
Report an issue: GitHub.