{"record":{"id":"eaaf6e2f240ac267","repo":"redis/redis-py","slug":"error-while-reading-from-host-error-e-args-eaaf6e","errorCode":null,"errorMessage":"Error while reading from {host_error}: {e.args}","messagePattern":"Error while reading from (.+?): (.+?)","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/connection.py","lineNumber":1391,"sourceCode":"            check_health=kwargs.get(\"check_health\", True),\n        )\n\n    def can_read(self, timeout: float = 0) -> bool:\n        \"\"\"Poll the socket to see if there's data that can be read.\"\"\"\n        # TODO: Rename this API; it detects pending data or dirty/closed\n        # connection state, not only whether application data can be read.\n        sock = self._sock\n        if not sock:\n            self.connect()\n\n        host_error = self._host_error()\n\n        try:\n            return self._parser.can_read(timeout)\n\n        except OSError as e:\n            self.disconnect()\n            raise ConnectionError(f\"Error while reading from {host_error}: {e.args}\")\n\n    def read_response(\n        self,\n        disable_decoding=False,\n        *,\n        timeout: Union[float, object] = SENTINEL,\n        disconnect_on_error=True,\n        push_request=False,\n    ):\n        \"\"\"Read the response from a previously sent command\"\"\"\n\n        host_error = self._host_error()\n\n        try:\n            if self.protocol in [\"3\", 3]:\n                response = self._parser.read_response(\n                    disable_decoding=disable_decoding,\n                    push_request=push_request,","sourceCodeStart":1373,"sourceCodeEnd":1409,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/connection.py#L1373-L1409","documentation":"Raised in can_read (connection.py:1389-1391) when the parser's can_read (a non-blocking poll for pending data) raises OSError. The connection is disconnected and a ConnectionError wraps the OS error args with the host:port for diagnostics. can_read is used to detect pending data or closed-connection state before/while waiting on a response.","triggerScenarios":"Calling a method that polls the socket (pubsub get_message with timeout, blocking commands, cluster slot checks) on a socket that is in an error/closed state — peer reset, local close, or corrupted fd. The OSError originates in the parser's select/read of the socket.","commonSituations":"Pubsub connection that died while waiting for messages; blocked BLPOP/BRPOP after a silent server disconnect; cluster client polling a stale node connection; fd reuse after fork without reconnect.","solutions":["Catch ConnectionError and reconnect (pubsub: resubscribe after reconnect; blocking call: re-issue).","Enable health_check_interval and socket_keepalive to surface dead sockets earlier.","Use ConnectionPool/Sentinel so broken connections are replaced transparently.","After fork, always create a fresh client (the pid check in on_connect invalidates inherited fds).","Inspect e.args for the underlying errno (ECONNRESET etc.) to confirm a network drop."],"exampleFix":"# before\nmsg = pubsub.get_message(timeout=1)  # raises on dead socket\n# after\ntry:\n    msg = pubsub.get_message(timeout=1)\nexcept redis.ConnectionError:\n    pubsub = r.pubsub(ignore_subscribe_messages=True)\n    pubsub.subscribe('ch')  # resubscribe","handlingStrategy":"try-catch","validationCode":"# Healthy defaults for pubsub / blocking-style polling\nr = redis.Redis(\n    host=h, port=p,\n    health_check_interval=30,\n    socket_keepalive=True,\n    socket_timeout=10,\n)\n# After fork, always create a NEW client (inherited fds are invalid)\nr = redis.Redis(host=h, port=p) if os.getpid() != creation_pid else r","typeGuard":"null","tryCatchPattern":"from redis.exceptions import ConnectionError\ndef safe_get_message(pubsub, timeout=1):\n    try:\n        return pubsub.get_message(timeout=timeout)\n    except ConnectionError:\n        # reconnect + resubscribe\n        pubsub = r.pubsub(ignore_subscribe_messages=True)\n        pubsub.subscribe(*channels)\n        return None","preventionTips":["Resubscribe to channels after reconnecting pubsub.","Never reuse connections across fork — rebuild the client post-fork.","Enable health checks + keepalive on pubsub/polling clients.","Inspect e.args for the errno to confirm a network drop."],"tags":["network","read","connection-reset","pubsub"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}