redis/redis-py · error · TimeoutError
Timeout reading from {host_error}
Error message
Timeout reading from {host_error} What it means
Raised as a TimeoutError from read_response() when self.socket_timeout (or the fallback) elapses before a full response is parsed. The connection is forcibly disconnected (nowait=True) because a partial read desynchronizes the protocol stream; the connection cannot be safely reused. Note: if the caller passed an explicit timeout=, the method returns None instead (so the operation can be retried) - this exception only fires for the socket_timeout path.
Source
Thrown at redis/asyncio/connection.py:1310
else:
async with timeout_context:
response = await self._read_response_from_parser(
disable_decoding=disable_decoding,
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 NoneView on GitHub (pinned to da03cdc7e8)
Solutions
- For blocking commands, pass an explicit timeout= to read_response (or use brpop(..., timeout=N)) so a timeout returns None instead of raising.
- Set socket_timeout=None or large enough to outlive the longest blocking call.
- Investigate server-side stalls (persistence fork, big Lua script, DEBUG SLEEP left on).
- Avoid mixing a tight socket_timeout with long-running server-side operations on the same client.
Example fix
// before
r = redis.asyncio.Redis(host=h, port=p, socket_timeout=1)
val = await r.brpop("queue") # blocks indefinitely -> TimeoutError after 1s
// after
r = redis.asyncio.Redis(host=h, port=p)
val = await r.brpop("queue", timeout=5) # returns None after 5s, no exception Defensive patterns
Strategy: validation
Validate before calling
def compatible_socket_timeout(blocking_call_seconds: float | None) -> float | None:
# socket_timeout must exceed any blocking command's wait
if blocking_call_seconds is None:
return None
return blocking_call_seconds * 2 Try / catch
from redis.exceptions import TimeoutError
val = await r.brpop("q", timeout=5) # explicit timeout returns None, no raise
if val is None:
pass # timed out cleanly Prevention
- Pass an explicit timeout= to blocking commands so timeouts return None.
- Don't set socket_timeout tighter than your longest blocking call.
- Use pubsub's math.inf blocking read where indefinite wait is intended.
When it happens
Trigger: read_response() with no explicit timeout while socket_timeout is set, awaiting a command that never completes (blocking commands like BLPOP with no data, or a hung server). Also when a RESP3 push/out-of-band response arrives mid-read and the parser blocks.
Common situations: Using blocking commands (BLPOP, BRPOP, WAIT) without passing an explicit timeout; socket_timeout smaller than the blocking operation's expected wait; server stalled (DEBUG SLEEP, fork save, AOF rewrite); pubsub get_message with the default socket_timeout.
Related errors
- Timeout writing to socket
- Timed out closing connection after {self.socket_connect_time
- Error while reading from {host_error}: {e.args}
- Error while reading from {host_error} : {e.args}
- Timeout reading from {host_error}
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/67d1fda577b373ec.json.
Report an issue: GitHub.