mastra-ai/mastra · error

Unknown ACP sessionId: ${sessionId}

Error message

Unknown ACP sessionId: ${sessionId}

What it means

The ACP agent keeps a sessionMap from ACP sessionId to Mastra threadId. Any prompt or notification referencing a sessionId that was never established via `newSession` (or whose mapping was lost) makes getThreadIdOrThrow throw 'Unknown ACP sessionId'.

Source

Thrown at mastracode/sdk/src/acp/agent.ts:35

/**
 * ACP Agent implementation that wraps a mastracode Controller.
 * Each instance represents one ACP connection from a client.
 */
export class MastraCodeAcpAgent implements Agent {
  private readonly connection: AgentSideConnection;
  private readonly controller: AgentController;
  private readonly session: Session;
  private readonly modes: AgentControllerMode[];
  private readonly unsubscribeSessionEvents: () => void;
  private readonly sessionMap = new Map<string, string>(); // sessionId -> threadId
  private currentPromptState: PromptState | null = null;
  private promptMutex: Promise<void> = Promise.resolve();

  private getThreadIdOrThrow(sessionId: string): string {
    const threadId = this.sessionMap.get(sessionId);
    if (!threadId) {
      throw new Error(`Unknown ACP sessionId: ${sessionId}`);
    }
    return threadId;
  }

  constructor(
    connection: AgentSideConnection,
    controller: AgentController,
    session: Session,
    modes: AgentControllerMode[],
  ) {
    this.connection = connection;
    this.controller = controller;
    this.session = session;
    this.modes = modes;

    // Register persistent event listener
    this.unsubscribeSessionEvents = this.session.subscribe(event => {
      handleAgentControllerEvent(event, this.currentPromptState, this.connection, this.session);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the client calls newSession and uses the returned sessionId for subsequent requests
  2. Recreate the session via newSession after an agent restart instead of reusing old ids
  3. Log the sessionMap keys on failure to spot id mismatch/stale ids
  4. Check the client is not fabricating or truncating session ids

Example fix

// before
await agent.prompt({ sessionId: 'stale-session-id', prompt: [...] });
// after
const { sessionId } = await agent.newSession({ cwd: process.cwd(), mcpServers: [] });
await agent.prompt({ sessionId, prompt: [...] });
Defensive patterns

Strategy: type-guard

Validate before calling

if (!sessionMap.has(sessionId)) {
  throw new Error(`session ${sessionId} not open; call newSession first`);
}

Type guard

const isKnownSession = (agent: AcpAgent, sessionId: string): boolean =>
  agent.hasSession(sessionId);

Try / catch

try {
  const threadId = agent.threadId(sessionId);
} catch (err) {
  if ((err as Error).message.startsWith('Unknown ACP sessionId')) {
    const { sessionId: fresh } = await agent.newSession({ cwd: process.cwd() });
    // retry with fresh session
  } else throw err;
}

Prevention

When it happens

Trigger: Any ACP RPC (prompt, cancel, session updates) calls `threadId(sessionId)` for a sessionId absent from `this.sessionMap` — e.g. the client sends a prompt for a session created in a previous process lifetime or never created via newSession.

Common situations: Client reconnects and reuses stale session ids after the agent process restarted; client bug sending an unopened session id; in-memory sessionMap lost on restart since it is not persisted.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/929470c17a176e2e. Report an issue: GitHub.