redis/redis-py · error · ConnectionError
Error while writing to socket. .
Error message
Error {err_no} while writing to socket. {errmsg}. What it means
Raised as ConnectionError from send_packed_command() when the underlying writer raises OSError (anything other than asyncio.TimeoutError). The library extracts errno + errmsg (defaulting err_no to 'UNKNOWN' if there is only one arg), disconnects nowait, and re-raises wrapped. Typical causes are broken-pipe, connection-reset, or EAGAIN on a dead socket.
Solutions
- Enable retry with RetryOnDisconnect or a backoff policy so transient resets are retried automatically.
- Lower the connection pool idle eviction and/or the server timeout so stale connections are pruned before reuse.
- Enable socket_keepalive so dead connections are detected proactively.
- Investigate failover/network stability if the errors are persistent rather than occasional.
Example fix
// before r = redis.asyncio.Redis(host=h) // after from redis.retry import Retry from redis.backoff import ExponentialBackoff r = redis.asyncio.Redis(host=h, retry=Retry(ExponentialBackoff(), 3), retry_on_error=[ConnectionError], socket_keepalive=True)
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
from redis.exceptions import ConnectionError
def is_socket_write_error(exc: BaseException) -> bool:
return isinstance(exc, ConnectionError) and 'writing to socket' in str(exc).lower() Try / catch
from redis.retry import Retry
from redis.backoff import ExponentialBackoff
from redis.exceptions import ConnectionError
r = redis.asyncio.Redis(
host=h,
retry=Retry(ExponentialBackoff(), 3),
retry_on_error=[ConnectionError],
socket_keepalive=True,
) Prevention
- Enable retry_on_error=[ConnectionError] for idempotent commands.
- Prune idle connections faster than the LB idle timeout.
- Enable socket_keepalive.
When it happens
Trigger: Any command sent on a connection whose TCP peer has closed/reset: server crash, failover, idle timeout evicting the connection, NAT reaping, or a proxy dropping the session. The first command after such an event surfaces here.
Common situations: Idle connection killed by a cloud LB (typical AWS ElastiCache idle timeout 60-300s); Redis failover to a replica; network partition; forked process sharing sockets; TLS session torn down remotely.
Related errors
- Error while reading from
- Error while writing to socket. .
- Error while reading from
- Error while reading from
- Timeout writing to socket
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/2029f551e57f70f7.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/connection.py:1201
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
async def send_command(self, *args: Any, **kwargs: Any) -> None:
"""Pack and send a command to the Redis server"""
await self.send_packed_command(
self.pack_command(*args), check_health=kwargs.get("check_health", True)
)
@deprecated_function(
version="8.0.0", reason="Use can_read() instead", name="can_read_destructive"View on GitHub (pinned to 6a6b581b48)