redis/redis-py · warning · ConnectionError
Connection has data
Error message
Connection has data
What it means
Raised by ensure_connection() when a pooled connection returned to the caller still has unread data on the socket (can_read() is True) and maintenance notifications are not enabled. A healthy pooled connection should be drained; leftover bytes mean a previous response was not fully read (or the socket is in a bad state), so the pool treats it as corrupt and refuses to hand it out.
Source
Thrown at redis/asyncio/connection.py:2873
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)
async def ensure_connection(self, connection: AbstractConnection):
"""Ensure that the connection object is connected and valid"""
await connection.connect()
# connections that the pool provides should be ready to send
# 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 await connection.can_read() and not self.maint_notifications_enabled():
raise ConnectionError("Connection has data") from None
except (ConnectionError, TimeoutError, OSError):
await connection.disconnect()
await connection.connect()
if await connection.can_read() and not self.maint_notifications_enabled():
raise ConnectionError("Connection not ready") from None
async def release(self, connection: AbstractConnection):
"""Releases the connection back to the pool"""
# Connections should always be returned to the correct pool,
# not doing so is an error that will cause an exception here.
async with self._lock:
self._in_use_connections.remove(connection)
if connection.should_reconnect():
await connection.disconnect()
self._available_connections.append(connection)
View on GitHub (pinned to da03cdc7e8)
Solutions
- Always fully consume command responses before the connection is released back to the pool (let the client API manage release).
- Guard against task cancellation around commands (use asyncio.shield or structured concurrency) so a response is not left half-read.
- If it recurs, set a lower socket timeout or enable health-check reconnection; report a parser bug if it persists with stock usage.
Example fix
// before
conn = await pool.get_connection()
await conn.send_command('GET', 'k')
# task cancelled before reading response -> conn returned with data
// after
conn = await pool.get_connection()
try:
await conn.send_command('GET', 'k')
resp = await conn.read_response()
finally:
await pool.release(conn) Defensive patterns
Strategy: try-catch
Validate before calling
# prefer the high-level API which manages release/drain for you
async with redis.client('GET', 'k') as r:
val = await r Type guard
def connection_is_clean(conn) -> bool:
import asyncio
try:
return not conn.can_read() if hasattr(conn, 'can_read') else True
except Exception:
return False Try / catch
from redis.exceptions import ConnectionError
try:
await pool.get_connection('GET')
except ConnectionError as e:
if 'Connection has data' in str(e):
await pool.disconnect()
# retry; pool will build a fresh connection Prevention
- Let the client API fully read responses before release.
- Avoid cancelling tasks mid-command; use asyncio.shield for critical reads.
- Use async with redis: to guarantee release.
When it happens
Trigger: A connection is returned to the pool before its previous response was fully consumed (e.g., an interrupted/partial read, a cancelled task mid-command), then retrieved again and checked in ensure_connection(). The first can_read() check at connection.py:2872 trips it.
Common situations: Task cancellation in the middle of reading a response; a custom command path that returns the connection early; protocol desync after a network blip; rarely, a parser bug.
Related errors
- Connection not ready
- Cannot disable maintenance notifications after enabling them
- Either maint_notifications_pool_handler or oss_cluster_maint
- "max_connections" must be a positive integer
- Too many connections
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/cd7147f89f16e38d.json.
Report an issue: GitHub.