diff --git a/src/acp-error-shapes.ts b/src/acp-error-shapes.ts index b612ae6..81a8ed7 100644 --- a/src/acp-error-shapes.ts +++ b/src/acp-error-shapes.ts @@ -126,6 +126,16 @@ export function extractAcpError(error: unknown): OutputErrorAcpPayload | undefin return extractAcpErrorInternal(error, 0); } +/** + * JSON-RPC Internal error (-32603) from session/load. + * Some agents (e.g. claude-agent-acp) cannot restore sessions after a process + * restart and return this code instead of a "resource not found" style error. + */ +export function isAcpInternalError(error: unknown): boolean { + const acp = extractAcpError(error); + return acp?.code === -32603; +} + export function isAcpResourceNotFoundError(error: unknown): boolean { const acp = extractAcpError(error); if (acp && RESOURCE_NOT_FOUND_ACP_CODES.has(acp.code)) { diff --git a/src/session-runtime.ts b/src/session-runtime.ts index 9fc8935..19564ca 100644 --- a/src/session-runtime.ts +++ b/src/session-runtime.ts @@ -3,7 +3,7 @@ import fs from "node:fs/promises"; import path from "node:path"; import { AcpClient } from "./client.js"; import { formatErrorMessage, normalizeOutputError } from "./error-normalization.js"; -import { isAcpResourceNotFoundError } from "./acp-error-shapes.js"; +import { isAcpInternalError, isAcpResourceNotFoundError } from "./acp-error-shapes.js"; import type { QueueOwnerActiveSessionController } from "./queue-owner-turn-controller.js"; import { type QueueOwnerMessage, @@ -345,7 +345,17 @@ function shouldFallbackToNewSession(error: unknown): boolean { if (error instanceof TimeoutError || error instanceof InterruptedError) { return false; } - return isAcpResourceNotFoundError(error); + // Resource not found — agent explicitly says session doesn't exist. + if (isAcpResourceNotFoundError(error)) { + return true; + } + // Internal error (-32603) — some agents (e.g. claude-agent-acp) return this + // when they cannot restore a session after process restart. Treat as + // recoverable and fall back to creating a fresh session. + if (isAcpInternalError(error)) { + return true; + } + return false; } async function runQueuedTask(