TimeoutError, what it means and how to fix it

A timeout is a deadline expiring: the operation was given a budget, the budget ran out, and the code stopped waiting. Python raises the built-in TimeoutError for OS-level waits (it is the same class socket.timeout has aliased since 3.10), and HTTP libraries raise their own Timeout types. The essential question is always which deadline fired, because a connect deadline and a read deadline indict completely different things.

What it looks like

import requests
requests.get("https://slow-service.example/report",
             timeout=2)        # server needed longer than 2s

Traceback (most recent call last):
  File "main.py", line 2, in <module>
requests.exceptions.ReadTimeout:
HTTPSConnectionPool(host='slow-service.example', port=443):
Read timed out. (read timeout=2)

# ReadTimeout: the server was reached; its answer was slow

The fix, in order

  1. Identify connect versus read. A connect timeout means the server could not be reached or did not accept in time (network, firewall dropping packets, a host that is down). A read timeout means the connection succeeded and the response took too long (a slow endpoint, a big report, an overloaded server). The class name in requests (ConnectTimeout, ReadTimeout) or the message in socket code says which.
  2. Measure before raising the number. Time the same request with curl or a browser. If it genuinely takes 20 seconds, a 30-second timeout is honest configuration; if it takes 200 ms there and times out in code, the timeout is a symptom of something else (a proxy, a wrong address, a stalled connection pool).
  3. Set timeouts as a pair for HTTP calls: timeout=(3, 30) gives a short connect budget and a longer read budget, rather than one number silently governing both. Every network call should have some timeout; the default in requests is none, which converts server hangs into frozen programs.
  4. Make slow work asynchronous or smaller instead of endlessly patient. Page results, ask for ranges, or switch to a job pattern (start, poll, download) when an operation's natural duration is minutes. Timeouts are for detecting failure, not for waiting out real work.
  5. In socket and database code, set the timeout where the connection is created, and handle the expiry as an expected branch (log, retry with backoff, or fail cleanly) rather than letting it surface as an unhandled crash.

If it still happens

Timeouts that appear only at certain hours are capacity stories: the server or a shared middlebox saturates on a schedule (backups, batch jobs, peak traffic). Correlate timestamps before touching the code; the fix belongs to capacity or scheduling, not to the client.

Common questions

What timeout value should I use? One derived from measurement: comfortably above the service's normal response time (its p95, if you know it) and below your callers' patience. The common failure modes are no timeout at all (hangs forever) and copying a 5-second default onto a report endpoint that legitimately needs a minute.

Is TimeoutError the same as socket.timeout? Since Python 3.10, yes: socket.timeout is an alias of the built-in TimeoutError, which itself sits under OSError. Code catching either catches both in modern Python, and the errno (110, connection timed out) appears for OS-level connect timeouts.

Related errors

ConnectionError · OSError · RuntimeError