redis/redis-py · error · ConnectionError

Error while reading from {host_error} : {e.args}

Error message

Error while reading from {host_error} : {e.args}

What it means

Raised as a ConnectionError from read_response() when the parser raises an OSError while reading. The connection is forcibly disconnected (nowait=True) because a partial read desynchronizes the protocol. The host:port (or UDS path) and the OSError args are included. This is the canonical 'broken socket while reading a response' failure.

Source

Thrown at redis/asyncio/connection.py:1314

                            push_request=push_request,
                        )
            else:
                response = await self._read_response_from_parser(
                    disable_decoding=disable_decoding,
                    push_request=push_request,
                )
        except asyncio.TimeoutError:
            if timeout is not None:
                # user requested timeout, return None. Operation can be retried
                return None
            # it was a self.socket_timeout error.
            if disconnect_on_error:
                await self.disconnect(nowait=True)
            raise TimeoutError(f"Timeout reading from {host_error}")
        except OSError as e:
            if disconnect_on_error:
                await self.disconnect(nowait=True)
            raise ConnectionError(f"Error while reading from {host_error} : {e.args}")
        except BaseException:
            # Also by default close in case of BaseException.  A lot of code
            # relies on this behaviour when doing Command/Response pairs.
            # See #1128.
            if disconnect_on_error:
                await self.disconnect(nowait=True)
            raise

        if self.health_check_interval:
            next_time = asyncio.get_running_loop().time() + self.health_check_interval
            self.next_health_check = next_time

        if isinstance(response, ResponseError):
            raise response from None
        return response

    async def _read_response_from_parser(
        self, disable_decoding: bool = False, push_request: bool | None = False

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Configure retry (retry_on_error=[ConnectionError]) with backoff so transient resets are retried automatically.
  2. Enable health_check_interval to evict dead connections before they are read from.
  3. Enable socket_keepalive so silent drops are detected by the kernel rather than failing the next read.
  4. Inspect e.args to distinguish ECONNRESET (peer closed) from EBADF (local misuse) or ETIMEDOUT.

Example fix

// before
r = redis.asyncio.Redis(host=h, port=p)

// after
from redis.backoff import ExponentialWithJitterBackoff
from redis.retry import Retry
from redis.exceptions import ConnectionError
retry = Retry(ExponentialWithJitterBackoff(), 3)
r = redis.asyncio.Redis(host=h, port=p, retry=retry, retry_on_error=[ConnectionError], health_check_interval=30)
Defensive patterns

Strategy: retry

Try / catch

from redis.exceptions import ConnectionError
for attempt in range(3):
    try:
        val = await r.get("k")
        break
    except ConnectionError as e:
        if "while reading from" in str(e):
            await asyncio.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: Any command's read_response() where the socket raises OSError mid-read: server closed the connection (ECONNRESET), TCP RST from a firewall, local socket already closed (EBADF), or the parser hit an IO error decoding the stream.

Common situations: Server restarted/crashed during a long-running command; idle connection reaped by a firewall (RST on next read); OOM-kill of the server; client/server on different subnets with packet loss; reusing a disconnected connection.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/f022574f1b8d1499.json. Report an issue: GitHub.