{"record":{"id":"189edb75fd26204a","repo":"vercel/ai","slug":"harnessid-recovered-this-turn-through-disk-repl","errorCode":null,"errorMessage":"${harnessId} recovered this turn through disk replay only and has no restored ACP process for a subsequent prompt.","messagePattern":"(.+?) recovered this turn through disk replay only and has no restored ACP process for a subsequent prompt\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness-acp/src/v1/acp-v1-harness.ts","lineNumber":1418,"sourceCode":"        skills: options.skills,\n        abortSignal: options.abortSignal,\n      });\n      if (options.responseFormat?.type === 'json') {\n        if (options.responseFormat.schema == null) {\n          throw unsupported({\n            harnessId,\n            message: `${harnessId} requires a JSON schema for structured output.`,\n          });\n        }\n        if (outputSchemaMapping == null) {\n          throw unsupported({\n            harnessId,\n            message: `${harnessId} does not support structured output through ACP.`,\n          });\n        }\n      }\n      if (replayOnly) {\n        throw new Error(\n          `${harnessId} recovered this turn through disk replay only and has no restored ACP process for a subsequent prompt.`,\n        );\n      }\n      if (options.abortSignal?.aborted) {\n        throw (\n          options.abortSignal.reason ??\n          new DOMException('Aborted', 'AbortError')\n        );\n      }\n      const prompt = convertHarnessPromptToACPTextBlocks({\n        prompt: options.prompt,\n        harnessId,\n      });\n      const model = options.model ?? defaultModelId;\n      const turnStartConfig = createACPTurnStartConfig({\n        prompt,\n        tools: options.tools ?? [],\n        builtinTools,","sourceCodeStart":1400,"sourceCodeEnd":1436,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-acp/src/v1/acp-v1-harness.ts#L1400-L1436","documentation":"This harness session was recovered from persisted disk state via event replay after the ACP bridge process was lost, but no live ACP agent process was restored. Disk replay can rebuild the conversation history, yet it cannot reconstitute a live ACP process, so the session is marked replay-only and cannot accept a new prompt (doPromptTurn). Callers must resume from a suspend/detach handle that includes a live bridge, or start a fresh session.","triggerScenarios":"Calling promptTurn (doPromptTurn in the session returned by createSession/createACPV1) on a session whose lifecycle data was recovered with recoveryStatus indicating disk replay only (replayOnly=true), e.g. after restoring from persisted ACP lifecycle data that lacked a live bridge connection.","commonSituations":"Resuming a harness session from persisted state after a machine/container restart where the ACP agent process died; restoring a session snapshot on a different host than the one that ran the original process; attempting a subsequent prompt after recovery reported 'disk replay' recovery instead of a restored bridge.","solutions":["Start a fresh session (createACPV1) and seed it with the replayed history instead of prompting the replay-only session.","Check the session's lifecycle data recovery/restoration status before prompting and only prompt sessions whose recovery restored a live ACP process.","If the bridge process is still alive on the original host, resume using the persisted bridge data (port/token/lastSeenEventId) so a live process is restored rather than replay-only.","Wrap promptTurn in try-catch and treat this as terminal for the session; migrate any pending work to a new session."],"exampleFix":"// before\nawait session.promptTurn({ prompt: 'continue' }); // throws: replay-only recovery\n// after\nconst recovery = sessionLifecycleData.recovery;\nif (recovery?.mode === 'disk-replay') {\n  session = await createACPV1({ /* fresh session, seed with replayed history */ });\n}\nawait session.promptTurn({ prompt: 'continue' });","handlingStrategy":"fallback","validationCode":"const isReplayOnly = (data) => data?.recovery?.mode === 'disk-replay' || data?.recovery?.replayOnly === true;\nif (isReplayOnly(lifecycleData)) { /* recreate session before prompting */ }","typeGuard":"function canPrompt(session: { lifecycle: { recovery?: { mode?: string } } }): boolean {\n  return session.lifecycle.recovery?.mode !== 'disk-replay';\n}","tryCatchPattern":"try {\n  await session.promptTurn({ prompt });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('disk replay only')) {\n    session = await createACPV1({ /* fresh session, seed replayed history */ });\n    await session.promptTurn({ prompt });\n  } else throw e;\n}","preventionTips":["Inspect recovery/restoration status in lifecycle data before prompting a recovered session","Prefer resume via live bridge data over disk-replay recovery when the original host is reachable","Treat replay-only sessions as read-only history sources; always prompt through a fresh session"],"tags":["acp","session-recovery","replay-only","state-restoration"],"backgroundTag":"session-recovery-no-live-process","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}