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
- Increase the timeout parameter on the bash tool call
- Run long-lived or slow commands in the background (nohup ... &) and poll output instead
- Split the work into smaller commands that each finish within the timeout
- Ensure the command is non-interactive (pass flags like -y, pipe stdin, set CI=1)
- 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
- Always set an explicit timeout sized to the command
- Background long-running daemons instead of running them in the foreground
- Make commands non-interactive (flags, CI env vars, </dev/null)
- Split long work into chunks under the timeout
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Command timed out after ${err.message.slice("timeout:".lengt
- Command exited with code ${result.exitCode}
- Failed to restart ${serverName}: server process did not exit
- ${out}\n\n[${message}]
- Failed to attach to ${path.basename(exe)} on ${cdpUrl}: ${(e
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d09fd0f78e4473d7.
Report an issue: GitHub.