The default 5-minute total timeout is too long for most services, and errors need distinct handling.
aiohttp's timeouts are set with aiohttp.ClientTimeout, on the session or per request (timeout=). The fields:
total: the whole operation including connection, sending and reading the body. Default 300 seconds.connect: acquiring a connection, including waiting for a free one in the pool.sock_connect: establishing a new TCP connection (default 30 seconds).sock_read: maximum gap between pieces of data read from the socket.
A total timeout raises asyncio.TimeoutError (the built-in TimeoutError on Python 3.11+). Socket-level timeouts raise aiohttp.ConnectionTimeoutError or aiohttp.SocketTimeoutError, which are also subclasses of TimeoutError, so except TimeoutError catches all of them.
The exception hierarchy under aiohttp.ClientError:
ClientResponseError(fromraise_for_status, with.status), plusContentTypeError,ClientConnectionErrorwithClientConnectorError(DNS failure, connection refused),ServerDisconnectedError,ClientOSErrorand SSL errors such asClientConnectorCertificateError,InvalidURL,ClientPayloadError(body was truncated or malformed).
A robust fetch catches TimeoutError and aiohttp.ClientError, logs, and retries only when safe. Retries are not built in; write a small loop with backoff or use a package such as aiohttp-retry or tenacity.
Set a sensible session-wide timeout, e.g. ClientTimeout(total=30, sock_connect=5), and override it for known slow endpoints.
Example
import asyncio
import aiohttp
async def fetch(session, path):
try:
async with session.get(path) as resp:
resp.raise_for_status()
return f"ok {resp.status}"
except TimeoutError:
return "timed out"
except aiohttp.ClientResponseError as e:
return f"HTTP {e.status}"
except aiohttp.ClientConnectionError as e:
return f"connection problem: {type(e).__name__}"
async def main():
timeout = aiohttp.ClientTimeout(total=2, sock_connect=1)
async with aiohttp.ClientSession("https://httpbin.org", timeout=timeout) as s:
print(await fetch(s, "/get")) # ok 200
print(await fetch(s, "/delay/5")) # timed out
print(await fetch(s, "/status/503")) # HTTP 503
async with aiohttp.ClientSession(timeout=timeout) as s:
print(await fetch(s, "http://localhost:1/")) # connection problem: ClientConnectorError
asyncio.run(main())Remember
- ClientTimeout(total, connect, sock_connect, sock_read); default total is 300 s
- Timeouts raise TimeoutError subclasses; other failures are aiohttp.ClientError
- Retries are not built in
Watch out for
- Relying on the 5-minute default total timeout in a latency-sensitive service.