redis/redis-py · error · TimeoutError

Timeout reading from socket

Error message

Timeout reading from socket

What it means

Raised by SocketBuffer._read_from_socket when sock.recv() raises socket.timeout with raise_on_timeout=True (the default). Pure-Python parser counterpart of error 21. redis.exceptions.TimeoutError (error_type=NETWORK), which does NOT subclass Python's builtin TimeoutError.

Solutions

  1. Raise socket_timeout to exceed the slowest expected command/block time.
  2. For blocking commands, keep their block argument below socket_timeout, or pass a higher per-call timeout.
  3. Avoid KEYS/SMEMBERS in production; use SCAN.
  4. Add retry with backoff for TimeoutError via retry_on_error=[TimeoutError].
  5. Inspect SLOWLOG GET and optimize long commands.

Example fix

# before
r = redis.Redis(socket_timeout=0.5)  # pure-Python path
r.blpop('q', timeout=10)  # -> TimeoutError: Timeout reading from socket

# after - timeout covers the block window
r = redis.Redis(socket_timeout=12)
r.blpop('q', timeout=10)
Defensive patterns

Strategy: retry

Validate before calling

def timeout_ok(r, block_seconds):
    st = r.connection_pool.connection_kwargs.get('socket_timeout')
    return st is None or st > block_seconds

Type guard

from redis.exceptions import TimeoutError as RedisTimeoutError

def is_socket_read_timeout(e: BaseException) -> bool:
    return isinstance(e, RedisTimeoutError) and str(e) == 'Timeout reading from socket'

Try / catch

from redis.exceptions import TimeoutError
import time
for attempt in range(3):
    try:
        return r.get('k')
    except TimeoutError:
        if attempt == 2:
            raise
        time.sleep(0.2 * (2 ** attempt))

Prevention

When it happens

Trigger: A pure-Python (non-hiredis) sync connection where a reply takes longer than socket_timeout to arrive: KEYS / SORT / bigkey GET, blocking commands (BLPOP/BZPOPMIN/XREAD BLOCK) whose block time exceeds socket_timeout, slow/congested network, server stalled under RDB/AOF load.

Common situations: Low socket_timeout against a loaded Redis; KEYS in production; BLPOP block time greater than the client socket_timeout; cross-region latency spikes; AOF fsync=always stalls.

Understand the failure class

Related errors


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

Appendix: source

Thrown at redis/_parsers/socket.py:77

        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:
                if not raise_on_timeout:
                    return False
                if timeout == 0:
                    raise TimeoutError("Timeout reading from socket")
            raise ConnectionError(f"Error while reading from socket: {ex.args}")
        finally:
            buf.seek(current_pos)
            if custom_timeout:
                sock.settimeout(self.socket_timeout)

View on GitHub (pinned to 6a6b581b48)