TimeoutError

One class for every "took too long": socket.timeout (3.10), asyncio.TimeoutError and concurrent.futures.TimeoutError (3.11) are now all aliases of it.

InheritsBaseException›Exception›OSError›TimeoutError
OS exceptionPython 3.3+Live demo
TimeoutError(*args)
Raised by
socket ops with settimeout(), asyncio.wait_for / asyncio.timeout, Future.result(timeout=…)
Message
'timed out' from sockets; often empty from asyncio / futures
Quick fix
retry with backoff, or raise the limit
Watch out
not a ConnectionError; subprocess.TimeoutExpired is not one either

Demo

Live evaluation
Raise it with a message. An empty message gives the bare class name — what asyncio and concurrent.futures produce.
Try:
Inputs
messagestrmessage
Code
raise TimeoutError('no reply from api.example.com after 5s')
Uncaught exception
TimeoutError: no reply from api.example.com after 5s

With an empty message the traceback line is just TimeoutError — that is what you see from asyncio.wait_for() and Future.result(timeout=…), so an empty message does not mean the error is broken. In Handle, a timeout is treated as transient: the loop retries and only reports the last error when every attempt timed out.

Constructor

NameTypeRequiredDescription
*argsobjectnoUsually a message ('timed out' for sockets). With (errno, strerror) it behaves like any OSError.

Attributes

AttributeTypeMeaning
argstupleThe message, e.g. ('timed out',) for sockets; empty for asyncio/futures timeouts.
errnoint | Noneerrno.ETIMEDOUT when the OS reported the timeout (e.g. a TCP connect that never got an answer); None otherwise.
strerrorstr | NoneThe OS text for ETIMEDOUT when set ('Connection timed out' on Linux).

Common patterns

Socket timeout
settimeout() makes blocking calls raise TimeoutError instead of hanging forever.
import socket
s = socket.create_connection(('example.com', 80), timeout=5)
try:
    data = s.recv(1024)
except TimeoutError:
    data = b''
asyncio deadline
asyncio.timeout() (3.11+) or wait_for() cancel the work and raise TimeoutError.
import asyncio
async def main():
    try:
        async with asyncio.timeout(10):
            await fetch_all()
    except TimeoutError:
        print('took longer than 10s')
Retry with exponential backoff
Timeouts are often transient. Retry a few times, waiting longer each time, then re-raise.
import time
for attempt in range(5):
    try:
        resp = call_api()
        break
    except (TimeoutError, ConnectionError):
        if attempt == 4:
            raise
        time.sleep(2 ** attempt)

Examples

1. Raise with a message
raise TimeoutError('no reply after 5s')
Returns
TimeoutError: no reply after 5s
2. The old names are aliases
import socket, asyncio, concurrent.futures (socket.timeout is TimeoutError, asyncio.TimeoutError is TimeoutError, concurrent.futures.TimeoutError is TimeoutError)
Returns
(True, True, True)
3. Future.result(timeout=…)
from concurrent.futures import Future Future().result(timeout=0)
Returns
TimeoutError
4. asyncio.wait_for()
import asyncio async def main(): await asyncio.wait_for(asyncio.Event().wait(), timeout=0) asyncio.run(main())
Returns
TimeoutError
5. errno ETIMEDOUT maps to it
import errno type(OSError(errno.ETIMEDOUT, 'Connection timed out')).__name__
Returns
'TimeoutError'
6. It is an OSError, not a ConnectionError
(issubclass(TimeoutError, OSError), issubclass(TimeoutError, ConnectionError))
Returns
(True, False)
7. subprocess.TimeoutExpired is separate
import subprocess issubclass(subprocess.TimeoutExpired, TimeoutError)
Returns
False

Pitfalls

1. except ConnectionError misses timeouts
TimeoutError and ConnectionError are siblings under OSError. Network retry code usually needs both.
ConnectionError only
try:
    raise TimeoutError('timed out')
except ConnectionError:
    r = 'retry'
r
TimeoutError: timed out
Both classes
try:
    raise TimeoutError('timed out')
except (ConnectionError, TimeoutError):
    r = 'retry'
r
'retry'
2. subprocess timeouts are not TimeoutError
subprocess.run(..., timeout=…) raises subprocess.TimeoutExpired, a SubprocessError. except TimeoutError lets it through.
except TimeoutError
import subprocess
try:
    raise subprocess.TimeoutExpired(['backup.sh'], 5)
except TimeoutError:
    r = 'timed out'
r
subprocess.TimeoutExpired: Command '['backup.sh']' timed out after 5 seconds
except TimeoutExpired
import subprocess
try:
    raise subprocess.TimeoutExpired(['backup.sh'], 5)
except subprocess.TimeoutExpired as e:
    r = f'{e.cmd} timed out after {e.timeout}s'
r
"['backup.sh'] timed out after 5s"
3. except OSError before except TimeoutError
TimeoutError is an OSError subclass, so a preceding except OSError takes it and the timeout branch never runs.
OSError first
try:
    raise TimeoutError('timed out')
except OSError:
    r = 'I/O failure'
except TimeoutError:
    r = 'retry later'
r
'I/O failure'
TimeoutError first
try:
    raise TimeoutError('timed out')
except TimeoutError:
    r = 'retry later'
except OSError:
    r = 'I/O failure'
r
'retry later'

When to use

Use it
  • Catching socket, asyncio and futures timeouts with one except clause
  • Raising it from your own code when a deadline passes
  • Retrying transient network slowness with backoff
Reach for something else
  • subprocess.run(timeout=…) → catch subprocess.TimeoutExpired
  • requests / httpx timeouts → their own exception classes (see the FAQ)
  • queue.get(timeout=…) → raises queue.Empty, not TimeoutError

Notes

CPython impl
Objects/exceptions.c — OSError(ETIMEDOUT, …) returns TimeoutError
Aliases
socket.timeout (3.10), asyncio.TimeoutError and concurrent.futures.TimeoutError (3.11) are all TimeoutError
Catch via
except OSError — but not except ConnectionError

FAQ

Since Python 3.10 there is none: socket.timeout is a deprecated alias, socket.timeout is TimeoutError is True. Before 3.10 socket.timeout was a separate OSError subclass, so code for older versions caught socket.timeout explicitly. New code should catch TimeoutError.

History

3.3
Added, together with the other OSError subclasses (PEP 3151).
3.10
socket.timeout made an alias of TimeoutError.
3.11
asyncio.TimeoutError and concurrent.futures.TimeoutError made aliases of TimeoutError.