{"record":{"id":"94dff8eb4da265ba","repo":"redis/redis-py","slug":"connection-not-ready","errorCode":null,"errorMessage":"Connection not ready","messagePattern":"Connection not ready","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/connection.py","lineNumber":2881,"sourceCode":"        # Note: We don't record IDLE here because async uses a sync make_connection\n        # but async record_connection_count. The recording is handled in get_connection.\n        return self.connection_class(**self.connection_kwargs)\n\n    async def ensure_connection(self, connection: AbstractConnection):\n        \"\"\"Ensure that the connection object is connected and valid\"\"\"\n        await connection.connect()\n        # connections that the pool provides should be ready to send\n        # a command. if not, the connection was either returned to the\n        # pool before all data has been read or the socket has been\n        # closed. either way, reconnect and verify everything is good.\n        try:\n            if await connection.can_read() and not self.maint_notifications_enabled():\n                raise ConnectionError(\"Connection has data\") from None\n        except (ConnectionError, TimeoutError, OSError):\n            await connection.disconnect()\n            await connection.connect()\n            if await connection.can_read() and not self.maint_notifications_enabled():\n                raise ConnectionError(\"Connection not ready\") from None\n\n    async def release(self, connection: AbstractConnection):\n        \"\"\"Releases the connection back to the pool\"\"\"\n        # Connections should always be returned to the correct pool,\n        # not doing so is an error that will cause an exception here.\n        async with self._lock:\n            self._in_use_connections.remove(connection)\n\n            if connection.should_reconnect():\n                await connection.disconnect()\n\n            self._available_connections.append(connection)\n\n        await self._event_dispatcher.dispatch_async(\n            AsyncAfterConnectionReleasedEvent(connection)\n        )\n\n        # Record state transition: USED -> IDLE","sourceCodeStart":2863,"sourceCodeEnd":2899,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/connection.py#L2863-L2899","documentation":"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.","triggerScenarios":"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.","commonSituations":"RESP3 server pushes not being consumed; a TCP proxy or sidecar injecting data; incompatible parser; server-side MONITOR/keepalive.","solutions":["If using RESP3 with server pushes, ensure maintenance notifications / push handling is configured so the data check is skipped.","Retry the operation once (the failure can be transient).","Check for a proxy that prepends data and verify parser/wire-protocol compatibility."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from redis.exceptions import ConnectionError\nfor attempt in range(retries):\n    try:\n        return await client.get(key)\n    except ConnectionError as e:\n        if 'Connection not ready' not in str(e):\n            raise\n        await asyncio.sleep(backoff(attempt))\nraise","preventionTips":["If using RESP3 pushes, enable maintenance notifications so the data check is bypassed.","Investigate proxies that inject bytes on connect if this recurs."],"tags":["connection","protocol","transient","async"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}