netdata/netdata · error · ReadTimeoutError

Read timed out. (read timeout=%s)

Error message

Read timed out. (read timeout=%s)

What it means

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.

Source

Thrown at src/collectors/python.d.plugin/python_modules/urllib3/connectionpool.py:309

        pass

    def _get_timeout(self, timeout):
        """ Helper that always returns a :class:`urllib3.util.Timeout` """
        if timeout is _Default:
            return self.timeout.clone()

        if isinstance(timeout, Timeout):
            return timeout.clone()
        else:
            # User passed us an int/float. This is for backwards compatibility,
            # can be removed later
            return Timeout.from_float(timeout)

    def _raise_timeout(self, err, url, timeout_value):
        """Is the error actually a timeout? Will raise a ReadTimeout or pass"""

        if isinstance(err, SocketTimeout):
            raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value)

        # See the above comment about EAGAIN in Python 3. In Python 2 we have
        # to specifically catch it and throw the timeout error
        if hasattr(err, 'errno') and err.errno in _blocking_errnos:
            raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value)

        # Catch possible read timeouts thrown as SSL errors. If not the
        # case, rethrow the original. We need to do this because of:
        # http://bugs.python.org/issue10272
        if 'timed out' in str(err) or 'did not complete (read)' in str(err):  # Python 2.6
            raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value)

    def _make_request(self, conn, method, url, timeout=_Default, chunked=False,
                      **httplib_request_kw):
        """
        Perform a request on a given urllib connection object taken from our
        pool.

View on GitHub (pinned to 4864de85e2)

Solutions

  1. Increase the read timeout: timeout=urllib3.Timeout(connect=5, read=60), sized to the endpoint's slowest legitimate response.
  2. 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.
  3. 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).
  4. Check server health (CPU, DB locks, GC pauses) when the timeout is intermittent.
  5. For large downloads, stream with preload_content=False and read in chunks so no single recv blocks past the window.

Example fix

# before
r = pool.urlopen('GET', '/slow-report', timeout=5)

# after
r = pool.urlopen('GET', '/slow-report', timeout=urllib3.Timeout(connect=5, read=120), retries=urllib3.util.retry.Retry(read=2))
Defensive patterns

Strategy: retry

Try / catch

from urllib3.exceptions import ReadTimeoutError, MaxRetryError

try:
    r = pool.urlopen('GET', url, timeout=urllib3.Timeout(connect=5, read=60))
except (ReadTimeoutError, MaxRetryError) as e:
    if 'Read timed out' in str(e):
        logger.warning('slow response from %s - consider raising read timeout', url)
        raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of netdata/netdata@4864de85e2 (2026-08-15). Data as JSON: /api/errors/08e1c4b9e18146d0. Report an issue: GitHub.