infiniflow/ragflow · error · RuntimeError

Command timed out

Error message

Command timed out

What it means

The generic timeout raised by `async_run_command` when the wrapped subprocess does not finish within `timeout` seconds (default 5). The process is killed and reaped before the error is raised. Callers pass various timeouts, e.g. the executor uses 5s for docker mkdir and TIMEOUT+5 for code execution, so the same message covers slow Docker CLI startup and genuinely slow commands.

Solutions

  1. Identify which call timed out from the traceback (mkdir vs run) and raise that step's timeout appropriately.
  2. Check Docker daemon health (`docker info`, `systemctl status docker`) if even trivial execs time out.
  3. For code execution timeouts, raise the sandbox TIMEOUT configuration or fix the user code that blocks.
  4. Retry once after the process is killed — transient daemon stalls often clear.

Example fix

# before
returncode, stdout, stderr = await async_run_command(*run_args, timeout=TIMEOUT + 5)

# after: distinguish startup slowness from user-code overrun and retry transient stalls
try:
    returncode, stdout, stderr = await async_run_command(*run_args, timeout=TIMEOUT + 5)
except RuntimeError as e:
    if "timed out" not in str(e):
        raise
    logger.warning("Execution hit %.0fs deadline for task %s", TIMEOUT + 5, task_id)
    raise TimeoutError(f"Code execution exceeded {TIMEOUT + 5}s") from e
Defensive patterns

Strategy: retry

Validate before calling

# Cheap daemon liveness probe before real work
rc, _, _ = await async_run_command("docker", "version", "--format", "{{.Server.Version}}", timeout=5)
if rc != 0:
    raise RuntimeError("Docker daemon unreachable")

Try / catch

import asyncio

async def run_with_retry(cmd, timeout, attempts=2):
    for i in range(attempts):
        try:
            return await async_run_command(*cmd, timeout=timeout)
        except RuntimeError as e:
            if "timed out" not in str(e) or i == attempts - 1:
                raise
            await asyncio.sleep(1)

Prevention

When it happens

Trigger: Any helper call whose subprocess exceeds its deadline: `docker exec mkdir` with an unresponsive Docker daemon or frozen container, or the code-run invocation when the user program blocks past TIMEOUT+5.

Common situations: Docker daemon overloaded or restarting; container I/O hung (NFS/fuse mount stall); cold-start latency on first docker invocation; user code with an infinite loop or long computation exceeding the configured execution timeout.

Understand the failure class

Related errors


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

Appendix: source

Thrown at agent/sandbox/executor_manager/utils/common.py:32

#  limitations under the License.
#
import asyncio
from typing import Tuple


async def async_run_command(*args, timeout: float = 5) -> Tuple[int, str, str]:
    """Safe asynchronous command execution tool"""
    proc = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)

    try:
        stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
        if proc.returncode is None:
            raise RuntimeError("Process finished but returncode is None")
        return proc.returncode, stdout.decode(), stderr.decode()
    except asyncio.TimeoutError:
        proc.kill()
        await proc.wait()
        raise RuntimeError("Command timed out")
    except Exception as e:
        proc.kill()
        await proc.wait()
        raise e

View on GitHub (pinned to 554fb1133a)