redis/redis-py · error · TimeoutError
Timeout writing to socket
Error message
Timeout writing to socket
What it means
Raised as a TimeoutError from send_packed_command() when self.socket_timeout is set and the write (writelines + drain) does not complete within that timeout. The connection is forcibly disconnected (nowait=True) before the error propagates, because a stuck write means the socket is unusable.
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 da03cdc7e8)
Solutions
- Increase socket_timeout to accommodate the largest expected command/pipeline size and worst-case latency.
- Reduce the size of pipelines/batches or stream large values (e.g. SCAN) instead of sending them at once.
- Investigate server-side pauses (slowlog, latency monitor, DEBUG SLEEP left running, memory pressure).
- Verify network bandwidth and TCP window scaling between client and server.
Example fix
// before r = redis.asyncio.Redis(host=h, port=p, socket_timeout=0.1) // after r = redis.asyncio.Redis(host=h, port=p, socket_timeout=5)
Defensive patterns
Strategy: retry
Validate before calling
def safe_socket_timeout(workload_seconds: float) -> float:
# at least 2x the expected worst-case command time
return max(1.0, workload_seconds * 2) Try / catch
from redis.exceptions import TimeoutError, ConnectionError
for attempt in range(3):
try:
await r.execute_command(*big_cmd)
break
except TimeoutError as e:
if "writing to socket" in str(e):
await asyncio.sleep(2 ** attempt)
continue
raise Prevention
- Size socket_timeout to the largest pipeline/transaction.
- Chunk very large writes instead of one giant pipeline.
- Monitor server slowlog / latency for stalls.
When it happens
Trigger: Calling any command (send_command/send_packed_command) with socket_timeout configured, where the underlying writer.drain() blocks longer than socket_timeout. Happens when the server or network stops draining the TCP send buffer (slow consumer, full kernel buffers).
Common situations: Pipelining/transactions with very large payloads that saturate the receive window; a server under extreme load or paused (DEBUG SLEEP, GC stall, swap thrash); a network link with high latency loss causing TCP backoff; socket_timeout set too low for the workload.
Related errors
- Timeout reading from {host_error}
- Timed out closing connection after {self.socket_connect_time
- Error {err_no} while writing to socket. {errmsg}.
- Timeout writing to socket
- Connection closed by server.
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/540ed7c6584947f8.json.
Report an issue: GitHub.