earendil-works/pi · error · Error
Agent is already processing. Wait for completion before rese
Error message
Agent is already processing. Wait for completion before resetting.
What it means
Agent.reset() clears transcript state, runtime state, and both message queues in one step; it refuses to run while activeRun exists because the in-flight loop holds a snapshot of the context and would keep emitting events into wiped state. The guard is a synchronous throw, so when it fires nothing has been cleared. The agent stays 'active' until the run and all awaited agent_end listeners have settled, not merely until the stream closes.
Source
Thrown at packages/agent/src/agent.ts:335
/** Abort the current run, if one is active. */
abort(): void {
this.activeRun?.abortController.abort();
}
/**
* Resolve when the current run and all awaited event listeners have finished.
*
* This resolves after `agent_end` listeners settle.
*/
waitForIdle(): Promise<void> {
return this.activeRun?.promise ?? Promise.resolve();
}
/** Clear transcript state, runtime state, and queued messages. */
reset(): void {
if (this.activeRun) {
throw new Error("Agent is already processing. Wait for completion before resetting.");
}
this._state.messages = [];
this._state.isStreaming = false;
this._state.streamingMessage = undefined;
this._state.pendingToolCalls = new Set<string>();
this._state.errorMessage = undefined;
this.clearFollowUpQueue();
this.clearSteeringQueue();
}
/** Start a new prompt from text, a single message, or a batch of messages. */
async prompt(message: AgentMessage | AgentMessage[]): Promise<void>;
async prompt(input: string, images?: ImageContent[]): Promise<void>;
async prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise<void> {
if (this.activeRun) {
throw new Error(
"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.",View on GitHub (pinned to 4af9d21d3b)
Solutions
- await agent.waitForIdle() before reset() - it resolves immediately when idle and after agent_end listeners settle when busy.
- If the run should be stopped, call agent.abort() first, then await agent.waitForIdle(), then reset().
- In UIs, disable or defer the reset action while agent.state.isStreaming is true.
Example fix
// before agent.abort(); agent.reset(); // throws: run still active // after agent.abort(); await agent.waitForIdle(); agent.reset();
Defensive patterns
Strategy: validation
Validate before calling
if (agent.state.isStreaming) {
await agent.waitForIdle(); // resolves after agent_end listeners settle
}
agent.reset(); Try / catch
try {
agent.reset(); // synchronous throw, nothing is cleared on failure
} catch (err) {
if (err instanceof Error && err.message.includes("before resetting")) {
agent.abort();
await agent.waitForIdle();
agent.reset(); // safe now
} else {
throw err;
}
} Prevention
- Centralize reset behind one async newConversation() helper that awaits waitForIdle first.
- After abort(), always await waitForIdle() before touching agent state.
- Remember the agent stays active until agent_end listeners settle, not just until the stream closes.
When it happens
Trigger: Calling agent.reset() while prompt() or continue() is still in flight; a UI 'new conversation' handler racing an in-progress turn; resetting in a listener that runs before agent_end listeners settle; calling abort() then reset() immediately without waiting for the abort to finish.
Common situations: Chat apps wiring a new-chat button to reset without awaiting the previous turn; tests resetting in afterEach while a slow stream drains; fire-and-forget prompt() calls that leave activeRun set longer than expected.
Related errors
- Agent is already processing a prompt. Use steer() or followU
- Agent is already processing. Wait for completion before cont
- No messages to continue from
- Cannot continue from message role: assistant
- not_found
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/28a645cba935edd9.
Report an issue: GitHub.