{"record":{"id":"08e1c4b9e18146d0","repo":"netdata/netdata","slug":"read-timed-out-read-timeout-s","errorCode":null,"errorMessage":"Read timed out. (read timeout=%s)","messagePattern":"Read timed out\\. \\(read timeout=(.+?)\\)","errorType":"exception","errorClass":"ReadTimeoutError","httpStatus":null,"severity":"error","filePath":"src/collectors/python.d.plugin/python_modules/urllib3/connectionpool.py","lineNumber":309,"sourceCode":"        pass\n\n    def _get_timeout(self, timeout):\n        \"\"\" Helper that always returns a :class:`urllib3.util.Timeout` \"\"\"\n        if timeout is _Default:\n            return self.timeout.clone()\n\n        if isinstance(timeout, Timeout):\n            return timeout.clone()\n        else:\n            # User passed us an int/float. This is for backwards compatibility,\n            # can be removed later\n            return Timeout.from_float(timeout)\n\n    def _raise_timeout(self, err, url, timeout_value):\n        \"\"\"Is the error actually a timeout? Will raise a ReadTimeout or pass\"\"\"\n\n        if isinstance(err, SocketTimeout):\n            raise ReadTimeoutError(self, url, \"Read timed out. (read timeout=%s)\" % timeout_value)\n\n        # See the above comment about EAGAIN in Python 3. In Python 2 we have\n        # to specifically catch it and throw the timeout error\n        if hasattr(err, 'errno') and err.errno in _blocking_errnos:\n            raise ReadTimeoutError(self, url, \"Read timed out. (read timeout=%s)\" % timeout_value)\n\n        # Catch possible read timeouts thrown as SSL errors. If not the\n        # case, rethrow the original. We need to do this because of:\n        # http://bugs.python.org/issue10272\n        if 'timed out' in str(err) or 'did not complete (read)' in str(err):  # Python 2.6\n            raise ReadTimeoutError(self, url, \"Read timed out. (read timeout=%s)\" % timeout_value)\n\n    def _make_request(self, conn, method, url, timeout=_Default, chunked=False,\n                      **httplib_request_kw):\n        \"\"\"\n        Perform a request on a given urllib connection object taken from our\n        pool.\n","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/netdata/netdata/blob/4864de85e26f6734d92cfc27ccbeff5921f49938/src/collectors/python.d.plugin/python_modules/urllib3/connectionpool.py#L291-L327","documentation":"Raised from ConnectionPool._raise_timeout (first branch) when the exception caught during _make_request is a socket.timeout raised by a blocking read/recv on the established connection. The TCP connection succeeded, but the server did not send a complete response within the read timeout. This is the classic server-side slowness timeout, distinct from a connect timeout.","triggerScenarios":"GET/POST via HTTPConnectionPool.urlopen where the server accepts the request, then stalls: slow backend script, lock contention, giant response streamed slower than the read timeout, or an idle keep-alive connection that the server closed without FIN being seen. timeout_value is the read timeout in effect (from Timeout.read or the float form).","commonSituations":"Default read timeout too small for a slow endpoint (report generation, heavy DB queries); keep-alive reuse of a connection that a load balancer silently dropped (idle timeout < LB keepalive); monitoring agents polling a slow status page; reverse proxy buffering a slow upstream.","solutions":["Increase the read timeout: timeout=urllib3.Timeout(connect=5, read=60), sized to the endpoint's slowest legitimate response.","Reproduce with curl -w '%{time_total}' to measure how long the endpoint actually takes; if it exceeds your timeout, fix the server or the timeout.","If it happens on reused connections after idle periods, disable keep-alive or set retries=Retry(read=1) and a smaller pool maxsize so stale connections are replaced (urllib3 re-tries idempotent requests).","Check server health (CPU, DB locks, GC pauses) when the timeout is intermittent.","For large downloads, stream with preload_content=False and read in chunks so no single recv blocks past the window."],"exampleFix":"# before\nr = pool.urlopen('GET', '/slow-report', timeout=5)\n\n# after\nr = pool.urlopen('GET', '/slow-report', timeout=urllib3.Timeout(connect=5, read=120), retries=urllib3.util.retry.Retry(read=2))","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from urllib3.exceptions import ReadTimeoutError, MaxRetryError\n\ntry:\n    r = pool.urlopen('GET', url, timeout=urllib3.Timeout(connect=5, read=60))\nexcept (ReadTimeoutError, MaxRetryError) as e:\n    if 'Read timed out' in str(e):\n        logger.warning('slow response from %s - consider raising read timeout', url)\n        raise","preventionTips":["Measure the endpoint's p99 response time and set read timeout above it (e.g. 2-3x).","Use Retry(read=2, backoff_factor=0.5) for idempotent GETs so one slow response is retried.","For big payloads, stream responses (preload_content=False) so no single recv waits for the whole body.","Keep-alive idle gaps shorter than any intermediary LB idle timeout to avoid semi-closed sockets."],"tags":["network","timeout","read-timeout","urllib3"],"backgroundTag":null,"analyzedSha":"4864de85e26f6734d92cfc27ccbeff5921f49938","analyzedAt":"2026-08-15T09:12:38.226Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}