redis/redis-py · error · ConnectionError

Connection not ready

Error message

Connection not ready

What it means

After 'Connection has data', ensure_connection disconnects and reconnects, then re-checks can_read(). If data is STILL present on a freshly connected socket (and maintenance notifications are not enabled), it raises ConnectionError('Connection not ready'). This indicates the server (or an intermediary) is injecting data immediately on connect, which the client cannot safely ignore.

Solutions

  1. If using RESP3 with server pushes, ensure maintenance notifications / push handling is configured so the data check is skipped.
  2. Retry the operation once (the failure can be transient).
  3. Check for a proxy that prepends data and verify parser/wire-protocol compatibility.
Defensive patterns

Strategy: retry

Try / catch

from redis.exceptions import ConnectionError
for attempt in range(retries):
    try:
        return await client.get(key)
    except ConnectionError as e:
        if 'Connection not ready' not in str(e):
            raise
        await asyncio.sleep(backoff(attempt))
raise

Prevention

When it happens

Trigger: A reconnect in ensure_connection succeeds but can_read() is true again right away, e.g. RESP3 push messages arriving before HELLO completes, a proxy prepending bytes, or server keepalive/monitor noise.

Common situations: RESP3 server pushes not being consumed; a TCP proxy or sidecar injecting data; incompatible parser; server-side MONITOR/keepalive.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/94dff8eb4da265ba. Report an issue: GitHub.

Appendix: source

Thrown at redis/asyncio/connection.py:2881

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

        await self._event_dispatcher.dispatch_async(
            AsyncAfterConnectionReleasedEvent(connection)
        )

        # Record state transition: USED -> IDLE

View on GitHub (pinned to 6a6b581b48)