{"record":{"id":"9ea4397e141c7e33","repo":"JuliusBrussee/caveman","slug":"agent-caveman-cloud-mcp-changed-after-setup-re","errorCode":null,"errorMessage":"${agent} caveman-cloud MCP changed after setup; refusing destructive bundle removal","messagePattern":"(.+?) caveman-cloud MCP changed after setup; refusing destructive bundle removal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":2614,"sourceCode":"    if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} failed skill postflight`);\n  }\n}\n\nfunction removeAgentNativeBundle(agent: \"claude\" | \"codex\"): void {\n  recoverPendingAgentNativeRemoval(agent);\n  recoverPendingAgentNativeBundle(agent);\n  const journal = readAgentNativeBundleJournal(agent);\n  if (!journal) {\n    process.stderr.write(`${mark(\"warn\")} ${agent}: no agent-native bundle journal found\\n`);\n    return;\n  }\n  for (const skill of journal.skills) {\n    const current = fileBytes(skill.file);\n    if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} changed after setup; refusing destructive bundle removal`);\n  }\n  const marker = readMcpServerMarker(agent, \"caveman-cloud\");\n  if (!sameMcpCommand(marker, journal.cloud_mcp) || !agentNativeCloudMcpMatches(agent, journal.cloud_mcp)) {\n    throw new Error(`${agent} caveman-cloud MCP changed after setup; refusing destructive bundle removal`);\n  }\n  if (journal.native_owned) {\n    const nativeJournal = readNativeJournal(agent);\n    if (nativeJournal) {\n      for (const operation of nativeJournal.operations) restoreNativeOperation(operation);\n    }\n  }\n  atomicWriteFile(agentNativeBundleRemovalJournalPath(agent), Buffer.from(JSON.stringify(journal, null, 2) + \"\\n\"));\n  try {\n    restoreAgentNativeBundleSkills(journal.skills);\n    restoreAgentNativeCloudMcp(agent, journal.previous_cloud_mcp);\n    if (journal.native_owned) disableNativeAgent(agent);\n    unlinkSync(agentNativeBundleJournalPath(agent));\n    unlinkSync(agentNativeBundleRemovalJournalPath(agent));\n  } catch (error) {\n    try {\n      restoreInstalledAgentNativeBundle(agent, journal);\n      unlinkSync(agentNativeBundleRemovalJournalPath(agent));","sourceCodeStart":2596,"sourceCodeEnd":2632,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/index.ts#L2596-L2632","documentation":"Safety gate in removeAgentNativeBundle: the live caveman-cloud MCP marker must still equal journal.cloud_mcp (sameMcpCommand) and the agent registration must still match (agentNativeCloudMcpMatches). If either drifted since setup, removal refuses to proceed so it does not clobber a registration that may contain newer user intent.","triggerScenarios":"Running `--remove` after the user or another tool changed the caveman-cloud MCP entry (different command, args, or resolved registration) relative to what the bundle journal recorded.","commonSituations":"User pointed caveman-cloud at a different binary or gateway; a second caveman version re-registered the MCP entry; agent re-serialized args.","solutions":["Re-run `caveman setup --agent-native <agent>` to re-register the MCP entry exactly as the journal expects, then run --remove","Or manually restore the caveman-cloud entry in the agent config to the journaled command/args, then remove","If the drift is intentional, delete the agent-native bundle journal only after manually confirming no skill/MCP state you care about will be orphaned"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before --remove: confirm live MCP equals the journal entry\nconst marker = readMcpServerMarker(agent, \"caveman-cloud\");\nif (!sameMcpCommand(marker, journal.cloud_mcp)) {\n  throw new Error(\"caveman-cloud entry drifted from journal; re-run setup before --remove\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await setup([\"--agent-native\", agent, \"--remove\"]);\n} catch (error) {\n  if (/caveman-cloud MCP changed after setup/.test((error as Error).message)) {\n    await setup([\"--agent-native\", agent]);      // re-register exactly as journaled\n    await setup([\"--agent-native\", agent, \"--remove\"]);\n  } else throw error;\n}","preventionTips":["Do not repoint the caveman-cloud MCP entry while a bundle is installed; remove the bundle first","Avoid running two caveman versions against the same agent config","Before --remove, diff the live MCP entry against what setup originally wrote"],"tags":["removal","safety-gate","mcp","config-drift"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}