redis/redis-py · error · ConnectionError

Error {errno} while writing to socket. {errmsg}.

Error message

Error {errno} while writing to socket. {errmsg}.

What it means

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.

Source

Thrown at redis/connection.py:1360

        # guard against health check recursion
        if check_health:
            self.check_health()
        try:
            if isinstance(command, str):
                command = [command]
            for item in command:
                self._sock.sendall(item)
        except socket.timeout:
            self.disconnect()
            raise TimeoutError("Timeout writing to socket")
        except OSError as e:
            self.disconnect()
            if len(e.args) == 1:
                errno, errmsg = "UNKNOWN", e.args[0]
            else:
                errno = e.args[0]
                errmsg = e.args[1]
            raise ConnectionError(f"Error {errno} while writing to socket. {errmsg}.")
        except BaseException:
            # BaseExceptions can be raised when a socket send operation is not
            # finished, e.g. due to a timeout.  Ideally, a caller could then re-try
            # to send un-sent data. However, the send_packed_command() API
            # does not support it so there is no point in keeping the connection open.
            self.disconnect()
            raise

    def send_command(self, *args, **kwargs):
        """Pack and send a command to the Redis server"""
        self.send_packed_command(
            self._command_packer.pack(*args),
            check_health=kwargs.get("check_health", True),
        )

    def can_read(self, timeout: float = 0) -> bool:
        """Poll the socket to see if there's data that can be read."""
        # TODO: Rename this API; it detects pending data or dirty/closed

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Enable retry_on_error=[ConnectionError] (or rely on the pool to hand a fresh connection on the next call).
  2. Set health_check_interval to detect dead connections before issuing commands.
  3. Investigate the embedded errno: EPIPE/ECONNRESET indicate the peer closed the connection.
  4. Stabilize the network path or increase keepalive to prevent idle drops.

Example fix

// before
r = redis.Redis(host=h)
// after
from redis.retry import Retry
from redis.backoff import ExponentialWithJitterBackoff
r = redis.Redis(host=h, retry_on_error=[redis.ConnectionError],
                retry=Retry(ExponentialWithJitterBackoff(), 3))
Defensive patterns

Strategy: retry

Try / catch

try:
    r.set('k', 'v')
except redis.exceptions.ConnectionError as e:
    if 'while writing to socket' in str(e):
        # peer dropped connection; pool yields a fresh one on retry
        r.set('k', 'v')

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/39000fb6bec459e0.json. Report an issue: GitHub.