redis/redis-py · error · TimeoutError

Timeout reading from

Error message

Timeout reading from {host_error}

What it means

Raised in read_response (connection.py:1416-1419) when socket.timeout fires while reading a reply. This is the read-side counterpart of the write timeout: the server did not produce a complete response within socket_timeout (or the per-call timeout). The connection is disconnected (unless disconnect_on_error=False) and redis.exceptions.TimeoutError is raised, including host:port.

Solutions

  1. Use the per-call timeout for blocking commands: brpop('q', timeout=30) and read via a client that passes timeout.
  2. Raise socket_timeout to exceed your slowest expected command.
  3. Avoid expensive commands on hot paths; prefer SCAN over KEYS.
  4. Set retry_on_timeout=True if timeouts are expected to be transient.
  5. For blocking commands, ensure the timeout argument and socket_timeout are consistent.

Example fix

# before
r = redis.Redis(host=h, port=p, socket_timeout=1)
r.brpop('queue', timeout=30)  # read times out at 1s
# after
r = redis.Redis(host=h, port=p, socket_timeout=35)
r.brpop('queue', timeout=30)
Defensive patterns

Strategy: retry

Validate before calling

# Align socket_timeout with your longest command/block
slowest = 35  # e.g. BLPOP timeout=30 plus margin
r = redis.Redis(
    host=h, port=p,
    socket_timeout=slowest,
    retry_on_timeout=True,
    retry=Retry(ExponentialBackoff(), 2),
)

Type guard

null

Try / catch

from redis.exceptions import TimeoutError
for _ in range(2):
    try:
        return r.brpop('queue', timeout=30)
    except TimeoutError as e:
        if 'reading from' in str(e):
            continue
        raise

Prevention

When it happens

Trigger: A command is sent and read_response is called with a socket_timeout that elapses before the full reply arrives — slow command (KEYS *, large ZRANGE, blocking BLPOP longer than timeout), server stalled, or an explicit per-call timeout passed to read_response that is shorter than the command duration.

Common situations: Blocking commands (BLPOP/BRPOP) with a socket_timeout shorter than the block duration; heavy O(N) commands (SORT, KEYS, SUNION); Lua scripts that run long; server under replication/AOF fsync stall; socket_timeout mis-sized for the workload.

Understand the failure class

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/44b2c0ff2a6232e6. Report an issue: GitHub.

Appendix: source

Thrown at redis/connection.py:1419

        """Read the response from a previously sent command"""

        host_error = self._host_error()

        try:
            if self.protocol in ["3", 3]:
                response = self._parser.read_response(
                    disable_decoding=disable_decoding,
                    push_request=push_request,
                    timeout=timeout,
                )
            else:
                response = self._parser.read_response(
                    disable_decoding=disable_decoding, timeout=timeout
                )
        except socket.timeout:
            if disconnect_on_error:
                self.disconnect()
            raise TimeoutError(f"Timeout reading from {host_error}")
        except OSError as e:
            if disconnect_on_error:
                self.disconnect()
            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:
                self.disconnect()
            raise

        if self.health_check_interval:
            self.next_health_check = time.monotonic() + self.health_check_interval

        if isinstance(response, ResponseError):
            try:
                raise response

View on GitHub (pinned to 6a6b581b48)