infiniflow/ragflow · error · TimeoutError
Operation timed out after {seconds} seconds and {attempts} a
Error message
Operation timed out after {seconds} seconds and {attempts} attempts. What it means
TimeoutError raised by the async branch of the @timeout decorator in common/connection_utils.py:64-94. For coroutine functions, each of `attempts` iterations runs the call under asyncio.wait_for(seconds) (only when ENABLE_TIMEOUT_ASSERTION is set); after the final attempt times out and neither on_timeout nor exception overrides were supplied, the default TimeoutError is raised. Callers can instead supply on_timeout (fallback value/callback) or exception (an exception class/instance to raise instead), which take precedence over this default.
Source
Thrown at common/connection_utils.py:86
for a in range(attempts):
try:
if os.environ.get("ENABLE_TIMEOUT_ASSERTION"):
return await asyncio.wait_for(func(*args, **kwargs), timeout=seconds)
else:
return await func(*args, **kwargs)
except asyncio.TimeoutError:
if a < attempts - 1:
continue
if on_timeout is not None:
if callable(on_timeout):
result = on_timeout()
if isinstance(result, Coroutine):
return await result
return result
return on_timeout
if exception is None:
raise TimeoutError(f"Operation timed out after {seconds} seconds and {attempts} attempts.")
if isinstance(exception, BaseException):
raise exception
if isinstance(exception, type) and issubclass(exception, BaseException):
raise exception(f"Operation timed out after {seconds} seconds and {attempts} attempts.")
raise RuntimeError("Invalid exception type provided")
if asyncio.iscoroutinefunction(func):
return async_wrapper
return wrapper
return decorator
async def construct_response(code=RetCode.SUCCESS, message="success", data=None, auth=None):
result_dict = {"code": code, "message": message, "data": data}View on GitHub (pinned to 554fb1133a)
Solutions
- Increase seconds (e.g. via the relevant config for LLM timeout) or attempts so the operation fits the budget.
- If a degraded-but-working behavior is acceptable, pass on_timeout=... to the decorator instead of letting the default TimeoutError propagate.
- Investigate the downstream dependency (LLM endpoint latency, ES query cost) — the decorator only reports the overrun.
- Pass exception=SomeSpecificError if callers need to distinguish this timeout from generic TimeoutErrors.
Example fix
# before @timeout(seconds=10) async def chat(...): ... # after @timeout(seconds=120, attempts=2, exception=LLMTimeoutError) async def chat(...): ...
Defensive patterns
Strategy: fallback
Validate before calling
if os.getenv("ENABLE_TIMEOUT_ASSERTION") and expected_p95_latency > configured_seconds:
raise RuntimeError(f"timeout budget {configured_seconds}s < p95 latency {expected_p95_latency}s — raise @timeout seconds") Try / catch
try:
out = await decorated_call()
except TimeoutError as e:
if "Operation timed out" in str(e):
return cached_or_default_result # fallback path
raise Prevention
- Pass on_timeout=... to the decorator when a degraded default beats raising.
- Budget seconds above the downstream p99 latency, especially for LLM calls.
- Use exception=CustomTimeoutError to make catches precise.
When it happens
Trigger: Awaiting an async function decorated with @timeout(seconds=N, attempts=M, exception=None, on_timeout=None) with ENABLE_TIMEOUT_ASSERTION set, where every asyncio.wait_for attempt exceeds N seconds — e.g. an async LLM/chat-completion call hanging past its budget on all retries.
Common situations: LLM provider slow or stalled (streaming connection open but no tokens); Elasticsearch/Infinity query exceeding the configured budget under load; test environments asserting timeouts; defaults too tight for reasoning-model requests.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Function '{func.__name__}' timed out after {seconds} seconds
- Command timed out
- Execution timed out after {exec_timeout} seconds
- Failed to fetch {current_url!r}: {_exc}
- Unexpected validation error: {e}
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/24355bd3065ad954.
Report an issue: GitHub.