FoundationAgents/OpenManus · error · TimeoutError

Command execution timed out after {timeout} seconds

Error message

Command execution timed out after {timeout} seconds

What it means

execute() wraps its read loop in asyncio.wait_for(timeout); if the terminal does not return to a shell prompt within the given seconds, asyncio.TimeoutError is converted to a built-in TimeoutError with this message. The read loop only finishes when the '$ ' prompt marker reappears after the echoed exit-code line, so any command that never returns to the prompt will trip it.

Source

Thrown at app/sandbox/core/terminal.py:214

                        if e.errno == socket.EWOULDBLOCK:
                            await asyncio.sleep(0.1)
                            continue
                        raise

                output = b"\n".join(result_lines).decode("utf-8")
                output = re.sub(r"\n\$ echo \$\$?.*$", "", output)

                return output

            if timeout:
                result = await asyncio.wait_for(read_output(), timeout)
            else:
                result = await read_output()

            return result.strip()

        except asyncio.TimeoutError:
            raise TimeoutError(f"Command execution timed out after {timeout} seconds")
        except Exception as e:
            raise RuntimeError(f"Failed to execute command: {e}")

    def _sanitize_command(self, command: str) -> str:
        """Sanitizes the command string to prevent shell injection.

        Args:
            command: Raw command string.

        Returns:
            Sanitized command string.

        Raises:
            ValueError: If command contains potentially dangerous patterns.
        """

        # Additional checks for specific risky commands
        risky_commands = [

View on GitHub (pinned to 52a13f2a57)

Solutions

  1. Pass a larger timeout for known-slow commands: await term.execute('npm install', timeout=600).
  2. Never launch interactive/daemon processes through this API — background them with nohup and redirect output: 'nohup server > /tmp/log 2>&1 &'.
  3. Close stdin for pipe-hungry commands by appending '< /dev/null'.
  4. Catch TimeoutError in the caller and decide: retry with a bigger budget, or kill the runaway process in the container.

Example fix

# before
out = await term.execute("pip install -r requirements.txt")

# after
out = await term.execute("pip install -r requirements.txt < /dev/null", timeout=600)
# servers/watchers must be detached instead:
out = await term.execute("nohup python -m http.server 8000 > /tmp/http.log 2>&1 &")
Defensive patterns

Strategy: try-catch

Validate before calling

BLOCKING = ('http.server', 'tail -f', 'npm start', 'runserver', 'top', 'mysql ')
if any(b in cmd for b in BLOCKING):
    cmd = f'nohup {cmd} > /tmp/cmd.log 2>&1 < /dev/null &'
timeout = timeout or default_timeout

Try / catch

try:
    out = await term.execute(cmd, timeout=120)
except TimeoutError as e:
    await term.execute('pkill -f "<pattern-of-cmd>" || true', timeout=10)
    out = await term.execute(cmd, timeout=600)  # bigger budget; session may need re-init (see error 46)

Prevention

When it happens

Trigger: Running blocking or interactive commands: servers (python -m http.server), watchers (tail -f), REPLs (python with no args), commands reading stdin (grep with no file), or simply a command that takes longer than the configured timeout (large pip/npm install).

Common situations: Default timeout too small for heavyweight installs; agent runs 'npm install' or 'apt-get update' with the default limit; command spawns a background process that inherits stdout and keeps the pipe from showing a clean prompt.

Understand the failure class

Related errors


AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15). Data as JSON: /api/errors/8300705032101a1b. Report an issue: GitHub.