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

  1. Enable retry with RetryOnDisconnect or a backoff policy so transient resets are retried automatically.
  2. Lower the connection pool idle eviction and/or the server timeout so stale connections are pruned before reuse.
  3. Enable socket_keepalive so dead connections are detected proactively.
  4. 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

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


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)