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
- Increase socket_timeout to comfortably exceed the slowest expected write.
- Reduce the size of pipeline batches / individual payloads.
- Diagnose server-side slowlog and CPU/memory pressure that stalls socket reads.
- 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
- Size socket_timeout above your largest write / slowest link.
- Keep pipeline batches bounded.
- Enable socket_keepalive to detect dead peers.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout reading from
- Error while writing to socket. .
- Timed out closing connection after
- Timeout writing to socket
- Connection closed by server.
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)