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
- Identify which call timed out from the traceback (mkdir vs run) and raise that step's timeout appropriately.
- Check Docker daemon health (`docker info`, `systemctl status docker`) if even trivial execs time out.
- For code execution timeouts, raise the sandbox TIMEOUT configuration or fix the user code that blocks.
- 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
- Size the timeout to the slowest legitimate step (docker cold start can take seconds).
- Probe the Docker daemon before dispatching bursty workloads.
- Bound user code with its own internal timeouts so the outer kill is a last resort.
- Distinguish 'Command timed out' from downstream TimeoutErrors in alerting.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Directory creation failed: {stderr}
- {stderr.decode()}
- Process finished but returncode is None
- Operation timed out after {seconds} seconds and {attempts} a
- Failed to create search
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/37e36c50cc86dd57.
Report an issue: GitHub.