{"record":{"id":"b455c880ee18c7e2","repo":"JuliusBrussee/caveman","slug":"cave-harness-agent-mismatch","errorCode":"cave_harness_agent_mismatch","errorMessage":"cave_harness_agent_mismatch","messagePattern":"cave_harness_agent_mismatch","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/execution-kernel.ts","lineNumber":79,"sourceCode":"}\n\nexport function prepareLockedHarnessExecution(input: {\n  build: CaveBuildLock;\n  harness: string;\n  adapterVersion: string;\n  upstreamVersion: string;\n  agentId?: string;\n  contextIR: ContextIR;\n  plan: CavePlan;\n}): LockedHarnessPreparation {\n  const build = parseCaveBuildLock(input.build);\n  if (build.harness.id !== input.harness ||\n      build.harness.adapter_version !== input.adapterVersion ||\n      build.harness.upstream_version !== input.upstreamVersion) {\n    throw new Error(\"cave_harness_build_mismatch\");\n  }\n  if (input.agentId !== undefined && build.agent_id !== input.agentId) {\n    throw new Error(\"cave_harness_agent_mismatch\");\n  }\n  if (stableStringify(input.plan) !== stableStringify(build.selected_plan)) {\n    throw new Error(\"cave_harness_plan_mismatch\");\n  }\n  const planSHA256 = sha256(stableStringify(input.plan));\n  if (planSHA256 !== build.plan_sha256) {\n    throw new Error(\"cave_harness_plan_digest_mismatch\");\n  }\n  const contextIRSHA256 = sha256(stableStringify(contextIRToWire(input.contextIR)));\n  if (contextIRSHA256 !== build.context_ir_sha256) {\n    throw new Error(\"cave_harness_context_ir_mismatch\");\n  }\n  const [provider, ...modelParts] = input.plan.model.split(\"/\");\n  const model = modelParts.join(\"/\");\n  if (!provider || !model) throw new Error(\"cave_harness_model_invalid\");\n  return Object.freeze({\n    build,\n    plan: build.selected_plan,","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/execution-kernel.ts#L61-L97","documentation":"Thrown while preparing a locked harness (packages/agent/src/execution-kernel.ts:79): an agentId was supplied for the execution but it differs from the build.agent_id recorded in the CaveBuildLock. A lock is bound to one specific agent definition; running it against another agent's id is rejected.","triggerScenarios":"Passing RunOptions/execution input with agentId set to a different agent than the one the lock was compiled from — e.g., reusing one agent's lock file for a sibling agent in the same project, or renaming an agent id after the lock was built.","commonSituations":"Multiple agents in one project sharing a lock path; renaming an agent's id in code without rebuilding; copy-pasting run code between agents while keeping the same lock reference.","solutions":["Regenerate the lock for the agent you are actually running (each agent gets its own lock).","Verify the agent id string passed at run time matches the id in agent({...}) used at build time (ids are lowercase, max 96 chars).","If the agent was renamed, rebuild all locks that referenced the old id."],"exampleFix":"// before\nconst lock = loadLock(\"cave-build.json\"); // built for agent \"researcher\"\nprepareLockedHarness({ build: lock, agentId: \"writer\", /* ... */ });\n\n// after\nconst lockForWriter = buildFor(agentDefinition(\"writer\"));\nprepareLockedHarness({ build: lockForWriter, agentId: \"writer\", /* ... */ });","handlingStrategy":"validation","validationCode":"const lock = parseCaveBuildLock(rawLock);\nif (input.agentId !== undefined && lock.agent_id !== input.agentId) {\n  throw new Error(`lock belongs to agent '${lock.agent_id}', got '${input.agentId}'`);\n}","typeGuard":null,"tryCatchPattern":"try { prepareLockedHarness(input); }\ncatch (e) {\n  if (e instanceof Error && e.message === \"cave_harness_agent_mismatch\") {\n    // fetch/build the lock for THIS agent id, then retry once\n    input = { ...input, build: await lockForAgent(input.agentId!) };\n    prepareLockedHarness(input);\n  } else throw e;\n}","preventionTips":["Derive lock paths from the agent id (one lock per agent) instead of a shared filename.","Rebuild locks after renaming any agent id.","Store the agent id in CI job configuration and assert it matches lock.agent_id before running."],"tags":["lockfile","agent-identity","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}