redis/redis-py · error · ConnectionError
Error while reading from
Error message
Error while reading from {host_error} : {e.args} What it means
Raised as ConnectionError from read_response() when the parser/reader raises OSError (not TimeoutError). Same path as the write-side OSError: the connection is disconnected nowait and re-raised with host_error and the OSError args. Note the message has a space before the colon, distinguishing it from the can_read variants.
Solutions
- Enable retry on ConnectionError with a bounded backoff for idempotent commands.
- Reduce response sizes or raise server client-output-buffer-limit to avoid mid-reply disconnects.
- Enable socket_keepalive to surface dead peers sooner.
- Verify the deployment is not running two clients on the same descriptor (no socket sharing across fork).
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_read_error(exc: BaseException) -> bool:
msg = str(exc).lower()
return isinstance(exc, ConnectionError) and 'reading from' in msg and ':' in msg 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 reads.
- Raise client-output-buffer-limit for large bulk replies.
- Never share a connection across forked processes.
When it happens
Trigger: Reading any response when the peer has reset/closed the socket mid-reply; partial RESP frame then RST; TLS truncation; reader feed_eof with exception. The first read after a dead-pool-reuse surfaces here.
Common situations: Server failover; LB idle eviction between request and response; client-output-buffer-limit disconnecting during a big bulk reply; forked process sharing the reader; abrupt server kill -9.
Related errors
- Error while writing to socket. .
- Error while reading from
- Error while reading from
- Timeout reading from
- Error while writing to socket. .
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/f022574f1b8d1499.
Report an issue: GitHub.
Appendix: 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 = FalseView on GitHub (pinned to 6a6b581b48)