redis/redis-py · error · ConnectionError
Error while writing to socket. .
Error message
Error {errno} while writing to socket. {errmsg}. What it means
Raised in send_packed_command (connection.py:1353-1360) as the generic OSError branch during socket.sendall, after the socket.timeout branch. The actual errno and OS message are formatted into the string (e.g. EPIPE, ECONNRESET, EBADF). The connection is disconnected first, then ConnectionError is raised wrapping the OS-level cause.
Solutions
- Catch ConnectionError and reconnect/retry the operation (the pool handles this for pooled clients).
- Ensure redis.ConnectionPool/Sentinel are used so dead connections are reaped and replaced.
- Lower socket TCP keepalive idle / LB idle timeout or enable socket_keepalive to detect dead peers sooner.
- Check INFO clients / maxclients on the server.
- Avoid sharing a single connection across threads; use the client/pool.
Example fix
# before
conn = redis.Redis(host=h, port=p).connection_manager # manual reuse
# after — let the pool recover
r = redis.Redis(host=h, port=p, socket_keepalive=True)
try:
r.set('k','v')
except redis.ConnectionError:
r.set('k','v') # pool opens a fresh connection Defensive patterns
Strategy: try-catch
Validate before calling
# Prefer pooled clients that recover automatically; tune keepalive
r = redis.Redis(
host=h, port=p,
socket_keepalive=True,
health_check_interval=30,
retry_on_error=[redis.ConnectionError],
retry=Retry(ExponentialBackoff(), 3),
) Type guard
null
Try / catch
from redis.exceptions import ConnectionError
for _ in range(3):
try:
r.set('k', 'v')
break
except ConnectionError:
continue # pool opens a fresh connection; safe for idempotent ops Prevention
- Use the connection pool / Sentinel so dropped connections are replaced.
- Enable socket_keepalive to detect broken peers faster.
- Watch INFO clients/maxclients and dmesg for OOM/resets.
- Don't share a single connection across threads.
When it happens
Trigger: The server reset the connection (ECONNRESET), the local socket was already closed (EBADF), a broken pipe because the peer closed (EPIPE), or any other non-timeout OSError while sending a command.
Common situations: Redis restarted/failed over under a long-lived connection; maxclients reached and the server drops you; firewall kill; LB idle timeout closing the socket; connection used after disconnect in another thread.
Related errors
- Error while writing to socket. .
- Error while reading from
- Error while reading from
- Error while reading from
- Error while reading from
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/39000fb6bec459e0.
Report an issue: GitHub.
Appendix: 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/closedView on GitHub (pinned to 6a6b581b48)