vercel/ai · error
Recovered ACP session is disposed.
Error message
Recovered ACP session is disposed.
What it means
createACPRecoveredSession's prompt() refuses to send prompts once the recovered session has been disposed (disposed flag set). The library throws this guard error because the underlying ACP session id is no longer usable after disposal.
Source
Thrown at packages/harness-acp/src/v1/bridge/recovered-session.ts:58
sessionId,
restorationResponse,
updates,
}: {
agent: acp.ClientContext;
sessionId: string;
restorationResponse: acp.ResumeSessionResponse | acp.LoadSessionResponse;
updates: ReturnType<typeof createACPRecoveredSessionUpdates>;
}): ACPActiveSession {
let disposed = false;
return {
sessionId,
newSessionResponse: {
sessionId,
...restorationResponse,
},
prompt: async prompt => {
if (disposed) {
throw new Error('Recovered ACP session is disposed.');
}
updates.clearErrors();
const response = agent.request<acp.PromptResponse, acp.PromptRequest>(
acp.methods.agent.session.prompt,
{ sessionId, prompt },
);
void response.then(
value => {
updates.enqueue({
kind: 'stop',
response: value,
stopReason: value.stopReason,
});
},
error => updates.reject(error),
);
return response;
},View on GitHub (pinned to 69428b1f8b)
Solutions
- Re-acquire the session via ensureSession (which restores/recreates it) instead of prompting the disposed instance.
- Track disposal (or listen for dispose) and stop issuing prompts on the old reference.
- Restructure retry logic so retries go through session re-resolution, not the stale session object.
Example fix
// before
await cachedSession.prompt({ prompt: 'hi' }); // may be disposed
// after
const session = await ensureSession(); // returns a live/recovered session
await session.prompt({ prompt: 'hi' }); Defensive patterns
Strategy: try-catch
Validate before calling
if (session.isDisposed?.()) throw new Error('Refusing to prompt: session already disposed');
// or track disposal yourself:
let disposed = false;
session.addEventListener?.('dispose', () => { disposed = true; }); Try / catch
try {
await session.prompt({ prompt });
} catch (error) {
if (error instanceof Error && error.message === 'Recovered ACP session is disposed.') {
const fresh = await ensureSession();
return fresh.prompt({ prompt });
}
throw error;
} Prevention
- Never cache recovered-session objects across lifecycle boundaries; re-resolve via ensureSession.
- Cancel pending prompts during shutdown.
- Guard concurrent dispose/prompt races with a single owner of the session lifecycle.
When it happens
Trigger: Calling prompt() on a recovered ACP session after dispose() was called — e.g. prompting after the bridge shut the session down, after a lifecycle teardown, or holding a stale session reference across a restart.
Common situations: Application code caching the session object and reusing it after an error path disposed it; concurrent shutdown racing an in-flight prompt attempt; retry logic replaying a prompt on a disposed session.
Related errors
- Invalid argument for parameter requests: requests must not b
- Invalid argument for parameter requests: request IDs must no
- Invalid argument for parameter requests: request IDs must be
- Invalid argument for parameter batch: batch must be a suppor
- ACP session initialization did not produce a session.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/a9961e963f549ba2.
Report an issue: GitHub.