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
- Ensure the client calls newSession and uses the returned sessionId for subsequent requests
- Recreate the session via newSession after an agent restart instead of reusing old ids
- Log the sessionMap keys on failure to spot id mismatch/stale ids
- 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
- Always create sessions via newSession and persist the returned id
- Re-create sessions after agent process restarts
- Track session lifecycle client-side and drop ids after close
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.