redis/redis-py · error · ConnectionError
Connection closed by server.
Error message
Connection closed by server.
What it means
Raised by the shared SocketBuffer._read_from_socket (used by both sync pure-Python RESP2/RESP3 parsers) when sock.recv() returns b'' — the TCP EOF meaning the server closed the connection. It is the canonical server-close signal for the sync pure-Python path.
Source
Thrown at redis/_parsers/socket.py:67
timeout: Union[float, object] = SENTINEL,
raise_on_timeout: Optional[bool] = True,
) -> bool:
sock = self._sock
socket_read_size = self.socket_read_size
marker = 0
custom_timeout = timeout is not SENTINEL
buf = self._buffer
current_pos = buf.tell()
buf.seek(0, SEEK_END)
if custom_timeout:
sock.settimeout(timeout)
try:
while True:
data = sock.recv(socket_read_size)
# an empty string indicates the server shutdown the socket
if isinstance(data, bytes) and len(data) == 0:
raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR)
buf.write(data)
data_length = len(data)
marker += data_length
if length is not None and length > marker:
continue
return True
except socket.timeout:
if raise_on_timeout:
raise TimeoutError("Timeout reading from socket")
return False
except NONBLOCKING_EXCEPTIONS as ex:
# if we're in nonblocking mode and the recv raises a
# blocking error, simply return False indicating that
# there's no data to be read. otherwise raise the
# original exception.
allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1)
if ex.errno == allowed:View on GitHub (pinned to 43bf5ac31a)
Solutions
- Enable health_check_interval and retry_on_error=[ConnectionError, TimeoutError].
- Set socket_keepalive=True.
- Tune Redis `timeout`.
- Catch ConnectionError and reconnect.
Example fix
# before
r = redis.Redis(host='redis')
r.get('k')
# after
r = redis.Redis(host='redis', health_check_interval=30,
socket_keepalive=True,
retry_on_error=[redis.ConnectionError, redis.TimeoutError]) Defensive patterns
Strategy: retry
Validate before calling
try:
assert r.ping()
except redis.ConnectionError:
r.close(); r = redis.Redis(...)
r.get('k') Type guard
def is_closed_error(exc: Exception) -> bool:
from redis.exceptions import ConnectionError
return isinstance(exc, ConnectionError) and 'closed by server' in str(exc) Try / catch
from redis.exceptions import ConnectionError
try:
return r.get('k')
except ConnectionError:
r = redis.Redis(...)
return r.get('k') Prevention
- health_check_interval everywhere in prod.
- retry_on_error for transient errors.
- socket_keepalive across LB/NAT.
When it happens
Trigger: Any sync pure-Python parser read when the server half-closes the socket: restart, `timeout`, CLIENT KILL, failover, proxy idle drop.
Common situations: Managed Redis/proxies reaping idle flows; rolling deploys; failover; maxmemory-clients eviction.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- Connection closed by server.
- Connection closed by server.
- Timeout reading from socket
- Error {err_no} while writing to socket. {errmsg}.
- Error while reading from {host_error} : {e.args}
AI-assisted analysis of redis/redis-py@43bf5ac31a (2026-08-06).
Data as JSON: /api/errors/6db4f9fbae128bc0.
Report an issue: GitHub.