redis/redis-py · error · TimeoutError

Timeout writing to socket

Error message

Timeout writing to socket

What it means

Raised as TimeoutError from send_packed_command() when asyncio.wait_for(_send_packed_command, self.socket_timeout) elapses before the writer drains. The library first disconnects the connection (nowait=True) and then raises, so the socket is dead. socket_timeout is the per-operation read/write budget.

Solutions

  1. Increase socket_timeout to comfortably exceed the slowest expected write.
  2. Reduce the size of pipeline batches / individual payloads.
  3. Diagnose server-side slowlog and CPU/memory pressure that stalls socket reads.
  4. Confirm socket_keepalive is enabled so dead peers are detected earlier rather than stalling until the write timeout.

Example fix

// before
r = redis.asyncio.Redis(host=h, socket_timeout=0.2)
// after
r = redis.asyncio.Redis(host=h, socket_timeout=5.0, socket_keepalive=True)
Defensive patterns

Strategy: retry

Validate before calling

def timeout_supports_payload(size_bytes: int, socket_timeout: float, bandwidth_bps: int) -> bool:
    return (size_bytes * 8) / bandwidth_bps < socket_timeout

Type guard

def is_write_timeout(exc: BaseException) -> bool:
    return isinstance(exc, TimeoutError) and 'writing to socket' in str(exc).lower()

Try / catch

from redis.retry import Retry
from redis.backoff import ExponentialBackoff

r = redis.asyncio.Redis(
    host=h,
    socket_timeout=5.0,
    retry=Retry(ExponentialBackoff(), 3),
    retry_on_timeout=True,
)

Prevention

When it happens

Trigger: Issuing any command while socket_timeout is set and the network/server cannot accept bytes fast enough; e.g. a large PIPELINE/MULTI bulk write, a slow server, or a saturated link. Also triggered by a server that has stopped reading from its socket buffer.

Common situations: Default-omitted socket_timeout suddenly set to a low value; large MULTI/EXEC or big value (MB-sized SET) against a constrained server; TCP send buffer full because the peer stopped draining; cross-region latency exceeding the configured timeout.

Understand the failure class

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/540ed7c6584947f8. Report an issue: GitHub.

Appendix: source

Thrown at redis/asyncio/connection.py:1193

            await self.connect_check_health(check_health=False)
        if check_health:
            await self.check_health()

        try:
            if isinstance(command, str):
                command = command.encode()
            if isinstance(command, bytes):
                command = [command]
            if self.socket_timeout:
                await asyncio.wait_for(
                    self._send_packed_command(command), self.socket_timeout
                )
            else:
                self._writer.writelines(command)
                await self._writer.drain()
        except asyncio.TimeoutError:
            await self.disconnect(nowait=True)
            raise TimeoutError("Timeout writing to socket") from None
        except OSError as e:
            await self.disconnect(nowait=True)
            if len(e.args) == 1:
                err_no, errmsg = "UNKNOWN", e.args[0]
            else:
                err_no = e.args[0]
                errmsg = e.args[1]
            raise ConnectionError(
                f"Error {err_no} while writing to socket. {errmsg}."
            ) from e
        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.
            await self.disconnect(nowait=True)
            raise

View on GitHub (pinned to 6a6b581b48)