{"record":{"id":"6c1bf51d15328a0b","repo":"redis/redis-py","slug":"timeout-reading-from-socket-6c1bf5","errorCode":null,"errorMessage":"Timeout reading from socket","messagePattern":"Timeout reading from socket","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"redis/_parsers/socket.py","lineNumber":89,"sourceCode":"\n                if length is not None and length > marker:\n                    continue\n                return True\n        except socket.timeout:\n            if raise_on_timeout:\n                raise TimeoutError(\"Timeout reading from socket\")\n            return False\n        except NONBLOCKING_EXCEPTIONS as ex:\n            # if we're in nonblocking mode and the recv raises a\n            # blocking error, simply return False indicating that\n            # there's no data to be read. otherwise raise the\n            # original exception.\n            allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1)\n            if ex.errno == allowed:\n                if not raise_on_timeout:\n                    return False\n                if timeout == 0:\n                    raise TimeoutError(\"Timeout reading from socket\")\n            raise ConnectionError(f\"Error while reading from socket: {ex.args}\")\n        finally:\n            buf.seek(current_pos)\n            if custom_timeout:\n                sock.settimeout(self.socket_timeout)\n\n    def can_read(self, timeout: float = 0) -> bool:\n        return bool(self.unread_bytes()) or self._read_from_socket(\n            timeout=timeout, raise_on_timeout=False\n        )\n\n    def read(self, length: int, timeout: Union[float, object] = SENTINEL) -> bytes:\n        length = length + 2  # make sure to read the \\r\\n terminator\n        # BufferIO will return less than requested if buffer is short\n        data = self._buffer.read(length)\n        missing = length - len(data)\n        if missing:\n            # fill up the buffer and read the remainder","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/redis/redis-py/blob/43bf5ac31a5d7538fad3b1928e717ba757048041/redis/_parsers/socket.py#L71-L107","documentation":"Raised by SocketBuffer._read_from_socket when a non-blocking recv (BlockingIOError/SSLWantReadError, matching errno) occurs with timeout == 0. It surfaces as redis.exceptions.TimeoutError — a zero-timeout poll found no data and the caller asked to be notified.","triggerScenarios":"can_read()/pubsub poll/health check with socket_timeout=0 against a busy server or a TLS connection whose plaintext isn't ready within the zero window.","commonSituations":"Setting socket_timeout=0; tight pubsub.get_message(timeout=0) loops on slow links; TLS yielding SSLWantReadError before handshake; overloaded single-threaded Redis.","solutions":["Use a small positive socket_timeout (e.g. 0.5s).","Pass an explicit positive timeout to pubsub.get_message().","Catch redis.TimeoutError and retry with backoff.","Scale Redis if it's genuinely too slow to respond."],"exampleFix":"# before\nr = redis.Redis(host='redis', socket_timeout=0)\nr.get('k')\n# after\nr = redis.Redis(host='redis', socket_timeout=0.5)","handlingStrategy":"retry","validationCode":"if socket_timeout == 0:\n    raise ValueError('use a positive socket_timeout')\nr = redis.Redis(host=host, socket_timeout=socket_timeout)","typeGuard":"def is_socket_timeout(exc: Exception) -> bool:\n    from redis.exceptions import TimeoutError\n    return isinstance(exc, TimeoutError) and 'Timeout reading from socket' in str(exc)","tryCatchPattern":"from redis.exceptions import TimeoutError\nimport time\nfor backoff in (0.1, 0.2, 0.4):\n    try:\n        return r.get('k')\n    except TimeoutError:\n        time.sleep(backoff)\nraise TimeoutError('redis read timed out after retries')","preventionTips":["Never set socket_timeout=0.","Give pubsub polls a real timeout.","Distinguish TimeoutError from hard failures in retry policy."],"tags":["network","timeout","sync","socket"],"analyzedSha":"43bf5ac31a5d7538fad3b1928e717ba757048041","analyzedAt":"2026-08-06T22:35:38.048Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}