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.

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)

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.