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

  1. Wait for the current run to finish before prompting again, or cancel the in-flight run.
  2. Increase the wait deadline if the prior run is legitimately long.
  3. Investigate why the prior run hangs (network stall, tool awaiting input) and abort it so waitForIdle resolves.
  4. 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

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

Related errors


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