{"id":"39000fb6bec459e0","repo":"redis/redis-py","slug":"error-errno-while-writing-to-socket-errmsg","errorCode":null,"errorMessage":"Error {errno} while writing to socket. {errmsg}.","messagePattern":"Error (.+?) while writing to socket\\. (.+?)\\.","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/connection.py","lineNumber":1360,"sourceCode":"        # guard against health check recursion\n        if check_health:\n            self.check_health()\n        try:\n            if isinstance(command, str):\n                command = [command]\n            for item in command:\n                self._sock.sendall(item)\n        except socket.timeout:\n            self.disconnect()\n            raise TimeoutError(\"Timeout writing to socket\")\n        except OSError as e:\n            self.disconnect()\n            if len(e.args) == 1:\n                errno, errmsg = \"UNKNOWN\", e.args[0]\n            else:\n                errno = e.args[0]\n                errmsg = e.args[1]\n            raise ConnectionError(f\"Error {errno} while writing to socket. {errmsg}.\")\n        except BaseException:\n            # BaseExceptions can be raised when a socket send operation is not\n            # finished, e.g. due to a timeout.  Ideally, a caller could then re-try\n            # to send un-sent data. However, the send_packed_command() API\n            # does not support it so there is no point in keeping the connection open.\n            self.disconnect()\n            raise\n\n    def send_command(self, *args, **kwargs):\n        \"\"\"Pack and send a command to the Redis server\"\"\"\n        self.send_packed_command(\n            self._command_packer.pack(*args),\n            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","sourceCodeStart":1342,"sourceCodeEnd":1378,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/connection.py#L1342-L1378","documentation":"Raised as a ConnectionError in send_packed_command when an OSError (other than timeout) occurs during socket.sendall. The errno and message from the OS exception are embedded. The connection is disconnected before raising. This covers low-level socket failures like broken pipe, connection reset, etc.","triggerScenarios":"Any OSError during write: the peer closed the socket (EPIPE / broken pipe), a reset (ECONNRESET), or the local socket was invalidated. Happens mid-command when the server or a network device drops the TCP connection.","commonSituations":"Server restart/crash dropping connections; firewall/NAT idle-timeout killing the connection; a proxy recycling the upstream; client and server on different networks with intermittent connectivity; forked process using a socket from the parent.","solutions":["Enable retry_on_error=[ConnectionError] (or rely on the pool to hand a fresh connection on the next call).","Set health_check_interval to detect dead connections before issuing commands.","Investigate the embedded errno: EPIPE/ECONNRESET indicate the peer closed the connection.","Stabilize the network path or increase keepalive to prevent idle drops."],"exampleFix":"// before\nr = redis.Redis(host=h)\n// after\nfrom redis.retry import Retry\nfrom redis.backoff import ExponentialWithJitterBackoff\nr = redis.Redis(host=h, retry_on_error=[redis.ConnectionError],\n                retry=Retry(ExponentialWithJitterBackoff(), 3))","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    r.set('k', 'v')\nexcept redis.exceptions.ConnectionError as e:\n    if 'while writing to socket' in str(e):\n        # peer dropped connection; pool yields a fresh one on retry\n        r.set('k', 'v')","preventionTips":["Set retry_on_error=[ConnectionError] and health_check_interval.","Investigate the embedded errno (EPIPE/ECONNRESET) for the root cause.","Use TCP keepalive to prevent idle NAT drops."],"tags":["network","connection-reset","write","transient"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}