Code review example: requests.get with no timeout can hang the handler forever in Python
Retired from the DiffDojo practice pool in October 2026; the review below is the canonical answer. An AI wrote this pull request for the task underneath. Read the diff and decide what you would say before you scroll to the review.
The task
Fetch the exchange rate
- get_rate(base, quote) fetches the FX rate from the upstream provider.
- The upstream is a third-party HTTP API that can be slow or hang.
- If the upstream stops sending data, the call must time out rather than wait indefinitely.
Adds the FX rate fetch: calls the upstream provider and returns the parsed rate using requests.
get_rate runs inside a request handler that serves the checkout page; the upstream provider occasionally stalls.
The diff
app/fx/rates.py+9The review
Issue 1: requests.get with no timeout can hang the handler forever
requestshas no default timeout. Without atimeout=,requests.getwaits as long as the socket keeps the connection open, indefinitely if the upstream accepts the connection and then stops sending bytes.- The context makes that fatal. This runs inside the checkout request handler against a provider that "occasionally stalls". One hung upstream call pins that worker; a few of them exhaust the pool and checkout stops responding for everyone. Requirement 3 asked for exactly the opposite.
- It never shows up in testing. Against a fast local stub the call returns instantly; the missing timeout only bites when the real upstream misbehaves.
The fix: pass an explicit timeout= (a socket-inactivity deadline, not a hard total). Where a stall should degrade gracefully, catch requests.Timeout at the appropriate caller boundary.
The fix
import requests
PROVIDER = "https://fx.example.com/rate"
def get_rate(base: str, quote: str) -> float:
resp = requests.get(
PROVIDER, params={"base": base, "quote": quote}, timeout=3
)
resp.raise_for_status()
return resp.json()["rate"]Why it matters
Every outbound HTTP call needs an explicit timeout. requests has *no* default timeout; other clients vary (HTTPX defaults to a 5s inactivity timeout), so whatever you use, verify and configure its timeout policy, a dependency that hangs must not become a dependency that hangs *you*.
Real-world stakes: a third party has a bad afternoon, your workers all block on it waiting for a response that never comes, and your own site goes down even though nothing in your code is broken, a cascading outage from one missing keyword argument. Omitted timeouts are one of the most common resilience bugs, and assistants leave them off because the happy-path call works without one.
The verdict
Request changes. requests.get with no timeout can hang the handler forever
Try a live one
Python PRs you have not seen the answer to.
Leave inline comments and a verdict, then see what you caught. Free, no signup.
Review a Python PR →