can1357/oh-my-pi · error
Timed out waiting for prior agent run to finish before promp
Error message
Timed out waiting for prior agent run to finish before prompting.
What it means
When TurnRecovery needs to prompt but a previous agent run is still active, it catches AgentBusyError and waits for the agent to go idle. If the deadline passes while the prior run is still busy, it gives up with this timeout error rather than deadlocking or interleaving runs.
Source
Thrown at packages/coding-agent/src/session/turn-recovery.ts:2478
*/
abortRetry(): void {
this.#retryAbortController?.abort();
// Note: _retryAttempt is reset in the catch block of _autoRetry
this.resolveRetry();
}
async #promptAgentWithIdleRetry(messages: AgentMessage[], options?: { toolChoice?: ToolChoice }): Promise<void> {
const deadline = Date.now() + 30_000;
for (;;) {
try {
await this.#host.agent.prompt(messages, options);
return;
} catch (err) {
if (!(err instanceof AgentBusyError)) {
throw err;
}
if (Date.now() >= deadline) {
throw new Error("Timed out waiting for prior agent run to finish before prompting.");
}
await this.#host.agent.waitForIdle();
}
}
}
/** Whether auto-retry is currently in progress */
get isRetrying(): boolean {
return this.#retryPromise !== undefined;
}
/** Whether auto-retry is enabled */
get autoRetryEnabled(): boolean {
return this.#host.settings.get("retry.enabled") ?? true;
}
/**
* Toggle auto-retry setting.View on GitHub (pinned to 9690622007)
Solutions
- Wait for the current run to finish before prompting again, or cancel the in-flight run.
- Increase the wait deadline if the prior run is legitimately long.
- Investigate why the prior run hangs (network stall, tool awaiting input) and abort it so waitForIdle resolves.
- Avoid issuing prompts from multiple callers concurrently; serialize prompt submission.
Example fix
// before await recovery.promptUnlessBusy(msg); // times out while previous run hangs // after if (agent.isBusy()) await agent.abort(); // clear the stuck run first await recovery.promptUnlessBusy(msg);
Defensive patterns
Strategy: try-catch
Validate before calling
if (!host.agent.isIdle()) {
// decide: wait, abort, or defer the prompt before entering recovery
}
Try / catch
try {
await recovery.prompt(msg);
} catch (err) {
if (err instanceof Error && err.message.includes("Timed out waiting for prior agent run")) {
await host.agent.abort(); // clear the stuck run, then retry once
await recovery.prompt(msg);
} else throw err;
} Prevention
- Serialize all prompt submission through one caller/queue.
- Abort obviously-stuck runs instead of letting them block new turns.
- Monitor agent idleness before submitting prompts programmatically.
- Keep per-run timeouts on tool calls so runs cannot hang indefinitely.
When it happens
Trigger: Prompting while a prior agent run is still executing and waitForIdle() repeatedly returns with the run still active until Date.now() exceeds the deadline; long-running tool call or hung model stream in the previous run.
Common situations: User sends a new message while a slow previous turn (long bash command, stuck streaming request) is still running; a background/queued prompt races an in-flight run; an aborted-but-not-cleaned-up run keeps the agent busy forever.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- native spelling thread stopped
- timed out: {command}
- Agent is already processing. Use steer() or followUp() to qu
- Failed to open auth database at '${dbPath}' after ${maxAttem
- OAuth refresh ownership was lost before persistence
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e34196119ac3fd62.
Report an issue: GitHub.