FoundationAgents/OpenManus · error · TimeoutError
Command '{cmd}' timed out after {timeout} seconds
Error message
Command '{cmd}' timed out after {timeout} seconds What it means
LocalFileOperator.run_command runs a subprocess and bounds process.communicate() with asyncio.wait_for(timeout) (default 120s). On expiry it kills the process and raises TimeoutError naming the command and limit. Note the kill is best-effort (ProcessLookupError swallowed) — child processes of a shell=True command may survive the kill.
Source
Thrown at app/tool/file_operators.py:91
process = await asyncio.create_subprocess_shell(
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
try:
stdout, stderr = await asyncio.wait_for(
process.communicate(), timeout=timeout
)
return (
process.returncode or 0,
stdout.decode(),
stderr.decode(),
)
except asyncio.TimeoutError as exc:
try:
process.kill()
except ProcessLookupError:
pass
raise TimeoutError(
f"Command '{cmd}' timed out after {timeout} seconds"
) from exc
class SandboxFileOperator(FileOperator):
"""File operations implementation for sandbox environment."""
def __init__(self):
self.sandbox_client = SANDBOX_CLIENT
async def _ensure_sandbox_initialized(self):
"""Ensure sandbox is initialized."""
if not self.sandbox_client.sandbox:
await self.sandbox_client.create(config=SandboxSettings())
async def read_file(self, path: PathLike) -> str:
"""Read content from a file in sandbox."""
await self._ensure_sandbox_initialized()View on GitHub (pinned to 52a13f2a57)
Solutions
- Pass an explicit, realistic timeout for slow steps: await op.run_command('npm ci', timeout=600).
- Detached long-running processes: append 'nohup ... > /tmp/log 2>&1 &' so the shell returns instantly and the log is read separately.
- For pipelines under shell=True, close inherited fds by redirecting every child: 'cmd > /tmp/out.log 2>&1 < /dev/null'.
- Catch TimeoutError, then verify the process tree is actually dead (pkill -f pattern) before retrying, since kill() may miss grandchildren.
Example fix
# before
rc, out, err = await op.run_command("python -m http.server 8000") # never exits -> TimeoutError
# after
rc, out, err = await op.run_command(
"nohup python -m http.server 8000 > /tmp/http.log 2>&1 < /dev/null &"
)
rc, out, err = await op.run_command("sleep 1 && cat /tmp/http.log") Defensive patterns
Strategy: try-catch
Validate before calling
rc, out, err = await op.run_command('test -d node_modules && echo yes || echo no')
slow = ('install', 'build', 'test', 'pytest', 'compile')
timeout = 600 if any(s in cmd for s in slow) else 120
rc, out, err = await op.run_command(cmd, timeout=timeout) Try / catch
try:
rc, out, err = await op.run_command(cmd, timeout=120)
except TimeoutError:
await op.run_command('pkill -f "<cmd-pattern>" || true', timeout=10) # kill survivors
rc, out, err = await op.run_command(cmd + ' > /tmp/cmd.log 2>&1 < /dev/null', timeout=600) Prevention
- Pass explicit timeouts matched to the command class.
- Detach servers/daemons with nohup + redirects; read logs separately.
- Redirect stdin/stdout of children so communicate() can finish.
- After a timeout, clean the process tree before retrying — kill() may miss grandchildren.
When it happens
Trigger: Any command exceeding the timeout passed (or the 120s default): package installs, test suites, builds; commands started with shell=True that spawn children holding the pipes open, so even a 'finished' parent blocks communicate(); forgetting to pass timeout for a known-slow step.
Common situations: 'npm install' / 'pip install' on cold caches; running a full test suite through the file operator; starting servers in the foreground; shell pipelines where a backgrounded child keeps stdout open.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Command execution timed out after {timeout} seconds
- Command execution timed out after {timeout or self.config.ti
- timed out: bash has not returned in {self._timeout} seconds
- Command '{cmd}' timed out after {timeout} seconds in sandbox
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/8a5d81b4707d5650.
Report an issue: GitHub.