{"record":{"id":"35db2e0b8da45641","repo":"vercel/ai","slug":"harnessid-cannot-perform-lossy-acp-rerun-withou","errorCode":null,"errorMessage":"${harnessId} cannot perform lossy ACP rerun without persisted start configuration and an ACP session identifier.","messagePattern":"(.+?) cannot perform lossy ACP rerun without persisted start configuration and an ACP session identifier\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness-acp/src/v1/acp-v1-harness.ts","lineNumber":1526,"sourceCode":"        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 (!turnInFlight) {\n        throw new Error(`${harnessId} has no in-flight ACP turn to continue.`);\n      }\n      if (lossyRerun) {\n        if (latestTurnStartConfig == null || latestACPSessionId == null) {\n          throw new Error(\n            `${harnessId} cannot perform lossy ACP rerun without persisted start configuration and an ACP session identifier.`,\n          );\n        }\n        assertRecoveryToolCatalog({\n          persisted: latestTurnStartConfig.tools,\n          current: options.tools ?? [],\n        });\n      }\n      return wireTurn({\n        emit: options.emit,\n        abortSignal: options.abortSignal,\n        start: () => {\n          if (!lossyRerun) return;\n          const turnStartConfig = latestTurnStartConfig!;\n          channel.send({\n            type: 'start',\n            prompt: turnStartConfig.prompt,\n            debug: turnStartConfig.debug,","sourceCodeStart":1508,"sourceCodeEnd":1544,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-acp/src/v1/acp-v1-harness.ts#L1508-L1544","documentation":"A lossy rerun continues a turn by re-sending the persisted 'start' configuration with a recoveryMode of 'lossy-rerun', which requires both the persisted turn start config (latestTurnStartConfig) and the original ACP session id (latestACPSessionId). If either is missing — for example recovery never captured them — the harness cannot reconstruct the turn and throws.","triggerScenarios":"Calling continueTurn with lossy rerun (recovery via bridge process loss) when lifecycle data lacks turnStartConfig or acpSessionId — e.g. recovery happened before the first 'start' was persisted, or the persisted state predates the first successful turn start.","commonSituations":"Restoring from an old or truncated persisted snapshot; a crash before the first turn start was checkpointed; resuming across hosts with partial lifecycle data; hand-constructed or migrated persisted state missing acpSessionId.","solutions":["Ensure the persisted lifecycle data includes both turnStartConfig and acpSessionId before attempting a lossy-rerun continue.","Fall back to a fresh promptTurn (replaying the original prompt) when the persisted start config is unavailable.","Only attempt lossy rerun when the recovery status confirms the original turn had been started (start config was checkpointed).","Re-create the session and re-send the original prompt if the persisted state cannot be completed."],"exampleFix":"// before\nawait session.continueTurn({ tools }); // lossy rerun; throws if config/sessionId missing\n// after\nif (lifecycle.turnStartConfig && lifecycle.acpSessionId) {\n  await session.continueTurn({ tools });\n} else {\n  await session.promptTurn({ prompt: originalPrompt, tools });\n}","handlingStrategy":"validation","validationCode":"function canLossyRerun(data) {\n  return data?.turnStartConfig != null && data?.acpSessionId != null;\n}\nif (!canLossyRerun(lifecycleData)) { /* fall back to fresh promptTurn */ }","typeGuard":"function hasLossyRerunState(d: unknown): d is { turnStartConfig: object; acpSessionId: string } {\n  return typeof d === 'object' && d !== null &&\n    'turnStartConfig' in d && 'acpSessionId' in d;\n}","tryCatchPattern":"try {\n  await session.continueTurn({ tools });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('lossy ACP rerun without persisted')) {\n    await session.promptTurn({ prompt: originalPrompt, tools });\n  } else throw e;\n}","preventionTips":["Verify persisted lifecycle data contains both turnStartConfig and acpSessionId before attempting recovery","Avoid resuming from truncated or pre-first-turn snapshots for lossy rerun","Always persist lifecycle data only after the first turn start was checkpointed"],"tags":["acp","recovery","lossy-rerun","persisted-state"],"backgroundTag":"missing-recovery-state","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}