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

  1. Increase seconds (e.g. via the relevant config for LLM timeout) or attempts so the operation fits the budget.
  2. If a degraded-but-working behavior is acceptable, pass on_timeout=... to the decorator instead of letting the default TimeoutError propagate.
  3. Investigate the downstream dependency (LLM endpoint latency, ES query cost) — the decorator only reports the overrun.
  4. 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

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

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/24355bd3065ad954. Report an issue: GitHub.