{"record":{"id":"7d24c2b11fe0a606","repo":"vercel/ai","slug":"the-persisted-acp-turn-start-configuration-is-inco","errorCode":null,"errorMessage":"The persisted ACP turn start configuration is incompatible with the current non-secret start configuration.","messagePattern":"The persisted ACP turn start configuration is incompatible with the current non-secret start configuration\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness-acp/src/v1/acp-v1-harness.ts","lineNumber":1786,"sourceCode":"    tools: turnStartConfig.tools,\n    builtinTools,\n    permissionMode: turnStartConfig.permissionMode,\n    permissionModeMapping,\n    mcpServers,\n    debug: turnStartConfig.debug,\n    authenticationProfile,\n    sessionMeta,\n    instructionMapping,\n    responseFormat: turnStartConfig.responseFormat,\n    outputSchemaMapping,\n    model: turnStartConfig.model,\n    modelMapping,\n  });\n  if (\n    current.configurationFingerprint !==\n    turnStartConfig.configurationFingerprint\n  ) {\n    throw new Error(\n      'The persisted ACP turn start configuration is incompatible with the current non-secret start configuration.',\n    );\n  }\n}\n\nfunction validateACPColdSessionConfiguration({\n  coldSession,\n  permissionMode,\n  authenticationProfile,\n  sessionMeta,\n  instructionMapping,\n  outputSchemaMapping,\n  modelMapping,\n  builtinTools,\n  permissionModeMapping,\n  mcpServers,\n  debug,\n}: {","sourceCodeStart":1768,"sourceCodeEnd":1804,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-acp/src/v1/acp-v1-harness.ts#L1768-L1804","documentation":"When a persisted ACP turn start configuration is loaded (e.g. during recovery/resume), validateACPTurnStartConfig recomputes a fingerprint from the persisted non-secret fields using the CURRENT runtime configuration (builtin tools, permission-mode mapping, model mapping, auth profile identity, session meta, etc.) and compares it to the persisted fingerprint. A mismatch means the runtime configuration changed since the state was persisted, so replaying the turn could behave differently than the original, and the harness refuses.","triggerScenarios":"Resuming/continuing a persisted turn after upgrading the harness or ACP implementation, changing builtinTools, model mapping, permission mode mapping, output schema mapping, authentication profile, sessionMeta, or mcpServers — any of which alters the recomputed configurationFingerprint.","commonSituations":"Deploying a new version of the harness/agent between persisting and resuming; editing provider tool catalogs or model IDs between runs; changing sessionMeta or auth profile across restarts; running the resume on a differently configured environment.","solutions":["Restore the same runtime configuration (builtin tools, mappings, auth profile, session meta, model mapping) that was active when the state was persisted.","Start a fresh session and replay the conversation history instead of resuming the incompatible persisted turn.","Check configuration fingerprints on lifecycle data before resuming and branch to a fresh session on mismatch.","Avoid upgrading the harness/agent version mid-session; resume persisted state with the same version that wrote it."],"exampleFix":"// before\nconst session = await resumeACPV1({ lifecycleData }); // config changed since persist -> throws\n// after\nif (computeFingerprint(currentConfig) !== lifecycleData.turnStartConfig.configurationFingerprint) {\n  session = await createACPV1({ /* fresh, matching config */ });\n} else {\n  session = await resumeACPV1({ lifecycleData });\n}","handlingStrategy":"validation","validationCode":"function fingerprintsMatch(lifecycle, currentRuntime) {\n  return lifecycle?.turnStartConfig?.configurationFingerprint ===\n    computeTurnStartFingerprint(currentRuntime);\n}\nif (!fingerprintsMatch(lifecycleData, currentConfig)) { /* start fresh session */ }","typeGuard":null,"tryCatchPattern":"try {\n  session = await resumeACPV1({ lifecycleData });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('incompatible with the current non-secret start configuration')) {\n    session = await createACPV1({ /* matching fresh config */ });\n  } else throw e;\n}","preventionTips":["Keep harness/agent versions identical between persisting and resuming","Do not change builtin tools, model/permission mappings, auth profile, or sessionMeta mid-session","Store the runtime config alongside persisted state and diff it before resuming"],"tags":["acp","fingerprint","configuration-drift","resume"],"backgroundTag":"configuration-fingerprint-mismatch","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}