{"id":"11509ccf0e5b87d8","repo":"redis/redis-py","slug":"error-while-reading-from-host-error-e-args","errorCode":null,"errorMessage":"Error while reading from {host_error}: {e.args}","messagePattern":"Error while reading from (.+?): (.+?)","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"warning","filePath":"redis/asyncio/connection.py","lineNumber":1228,"sourceCode":"            raise\n\n    async def send_command(self, *args: Any, **kwargs: Any) -> None:\n        \"\"\"Pack and send a command to the Redis server\"\"\"\n        await self.send_packed_command(\n            self.pack_command(*args), check_health=kwargs.get(\"check_health\", True)\n        )\n\n    @deprecated_function(\n        version=\"8.0.0\", reason=\"Use can_read() instead\", name=\"can_read_destructive\"\n    )\n    async def can_read_destructive(self) -> bool:\n        \"\"\"Check the socket to see if there's data loaded in the buffer.\"\"\"\n        try:\n            return await self._parser.can_read()\n        except OSError as e:\n            await self.disconnect(nowait=True)\n            host_error = self._host_error()\n            raise ConnectionError(f\"Error while reading from {host_error}: {e.args}\")\n\n    async def can_read(self) -> bool:\n        \"\"\"Check the socket to see if there's data loaded in the buffer.\"\"\"\n        # TODO: Rename this API; it detects pending data or dirty/closed\n        # connection state, not only whether application data can be read.\n        try:\n            return await self._parser.can_read()\n        except OSError as e:\n            await self.disconnect(nowait=True)\n            host_error = self._host_error()\n            raise ConnectionError(f\"Error while reading from {host_error}: {e.args}\")\n\n    async def read_response(\n        self,\n        disable_decoding: bool = False,\n        timeout: float | None = None,\n        *,\n        disconnect_on_error: bool = True,","sourceCodeStart":1210,"sourceCodeEnd":1246,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/connection.py#L1210-L1246","documentation":"Raised as a ConnectionError from the deprecated can_read_destructive() when the parser's can_read() raises an OSError. The connection is forcibly disconnected. This method is deprecated (use can_read() instead); the error indicates a read failure while probing the buffer for pending data.","triggerScenarios":"Calling the deprecated can_read_destructive() (emits a deprecation warning since 8.0.0) and the underlying parser.can_read() hits an OSError - typically a socket already closed by the peer or a half-open connection.","commonSituations":"Legacy code written against an older redis-py API; pubsub loops probing for data; a peer that closed the connection between the probe and the read.","solutions":["Replace can_read_destructive() with can_read() - the deprecated form will be removed.","Guard the call in try/except for ConnectionError and reconnect on failure.","Use the higher-level PubSub.get_message(timeout=...) API instead of manual readiness probes."],"exampleFix":"// before\nif await conn.can_read_destructive():\n    ...\n\n// after\nif await conn.can_read():\n    ...","handlingStrategy":"validation","validationCode":"import warnings\n# Stop using the deprecated API entirely:\n# replace can_read_destructive() with can_read().\nwarnings.filterwarnings(\"error\", category=DeprecationWarning, module=\"redis\")","typeGuard":null,"tryCatchPattern":"from redis.exceptions import ConnectionError\ntry:\n    ready = await conn.can_read()  # use the non-deprecated form\nexcept ConnectionError:\n    conn = await pool.get_connection()","preventionTips":["Migrate off can_read_destructive() to can_read().","Prefer PubSub.get_message over manual readiness probes.","Treat DeprecationWarnings as errors in CI."],"tags":["deprecated","read","network","pubsub","async"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}