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

  1. Re-acquire the session via ensureSession (which restores/recreates it) instead of prompting the disposed instance.
  2. Track disposal (or listen for dispose) and stop issuing prompts on the old reference.
  3. 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

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


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/a9961e963f549ba2. Report an issue: GitHub.