can1357/oh-my-pi · error · ToolError

Command timed out

Error message

Command timed out

What it means

BashTool enforces a wall-clock timeout on commands it runs. When the spawned command does not exit within the requested timeoutSec, the tool kills the process and throws ToolError("Command timed out") instead of returning a result. This surfaces the timeout to the agent so it can retry with a longer timeout, run the command in the background, or split the work.

Source

Thrown at packages/coding-agent/src/tools/bash.ts:1225

				if (createRaced.kind === "aborted" || signal?.aborted) {
					cleanupLateCreate(createP);
					throw new ToolAbortError("Command aborted");
				}
				if (createRaced.kind === "timeout") {
					cleanupLateCreate(createP);
					const timedOutResult: BashInteractiveResult = {
						output: "",
						exitCode: undefined,
						cancelled: false,
						timedOut: true,
						truncated: false,
						totalLines: 0,
						totalBytes: 0,
						outputLines: 0,
						outputBytes: 0,
					};
					this.#throwIfUnfinished(timedOutResult, timeoutSec, this.#formatResultOutput(timedOutResult));
					throw new ToolError("Command timed out");
				}

				handle = createRaced.handle;

				// Emit partial update so the editor can embed the live terminal card.
				onUpdate?.({ content: [], details: { terminalId: handle.terminalId } });

				const exitPromise = handle.waitForExit();
				let exitStatus!: ClientBridgeTerminalExitStatus;

				type BridgeRaceResult =
					| { kind: "exit"; status: ClientBridgeTerminalExitStatus }
					| { kind: "poll" }
					| { kind: "timeout" }
					| { kind: "aborted" };

				const exitRacer = exitPromise.then(status => ({ kind: "exit" as const, status }));
				const abortRacer = abortedP.then(() => ({ kind: "aborted" as const }));

View on GitHub (pinned to 9690622007)

Solutions

  1. Increase the timeout parameter on the bash tool call
  2. Run long-lived or slow commands in the background (nohup ... &) and poll output instead
  3. Split the work into smaller commands that each finish within the timeout
  4. Ensure the command is non-interactive (pass flags like -y, pipe stdin, set CI=1)
  5. Check for accidental blocking on stdin/prompt and redirect </dev/null

Example fix

// before
await bash.execute("npm run build"); // default timeout, big build times out
// after
await bash.execute("npm run build", { timeout: 600 });
Defensive patterns

Strategy: try-catch

Validate before calling

// estimate: skip the call if the command classically exceeds budget
const LONG = /^(npm (install|run (build|test))|cargo build|docker build)/;
if (LONG.test(cmd)) console.warn("use an elevated timeout or background this command");

Try / catch

try {
  const res = await bash.execute(cmd, { timeout: 300 });
} catch (e) {
  if (e instanceof ToolError && e.message === "Command timed out") {
    // retry with larger timeout or background the command
  } else throw e;
}

Prevention

When it happens

Trigger: Running a command via the bash tool whose execution time exceeds the timeout passed to the execute call (or the session default). The raced timeout promise wins over the exit promise, the process is killed, and this error is thrown.

Common situations: Long builds (npm install, cargo build), commands that wait on user input (prompts), network operations on slow connections, accidentally interactive commands (editors, password prompts), and daemon-style commands that never exit (servers started in foreground).

Understand the failure class

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d09fd0f78e4473d7. Report an issue: GitHub.