{"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":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":2934,"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":2916,"sourceCodeEnd":2952,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L2916-L2952","documentation":"Thrown by removeAgentNativeBundle when the caveman-cloud MCP registration no longer matches what the journal recorded at setup: either the marker differs from journal.cloud_mcp via sameMcpCommand, or agentNativeCloudMcpMatches fails. Like the skill-file guard, this refuses destructive removal when the MCP entry changed after setup.","triggerScenarios":"Running `caveman setup --agent-native <agent> --remove` after the agent's caveman-cloud MCP entry was modified, replaced, or removed by the agent CLI, another tool, or manual config editing since setup.","commonSituations":"Agent auto-update restructured its MCP config; user manually tuned the MCP server entry; another caveman version or project re-registered caveman-cloud with a different command; multi-machine config sync overwrote the entry.","solutions":["Inspect the agent's MCP config for caveman-cloud and either restore the setup-time command/args or delete the entry manually, then re-run --remove.","Re-run `caveman setup --agent-native <agent>` to refresh the journal's cloud_mcp record to current values, then --remove.","Identify what rewrote the entry (agent update, another tool) and disable that rewriter before removing.","If the current registration is intentionally different and you accept manual cleanup, remove the MCP entry and skill files by hand instead of --remove."],"exampleFix":"// before: marker points at old node binary after upgrade\n\"caveman-cloud\": { \"command\": \"/usr/local/bin/node18\" }\n// after: refresh journal then remove\n$ caveman setup --agent-native claude\n$ caveman setup --agent-native claude --remove","handlingStrategy":"validation","validationCode":"const marker = readMcpServerMarker(agent, \"caveman-cloud\");\nif (!sameMcpCommand(marker, journal.cloud_mcp) || !agentNativeCloudMcpMatches(agent, journal.cloud_mcp)) {\n  console.error(\"caveman-cloud entry drifted; refresh with setup before --remove\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  removeAgentNativeBundle(agent);\n} catch (err) {\n  if (/MCP changed after setup/.test((err as Error).message)) {\n    console.error(\"Re-run `caveman setup --agent-native \" + agent + \"` to refresh the journal, then remove\");\n  }\n}","preventionTips":["Don't manually edit the caveman-cloud MCP entry while a bundle is installed.","Disable tools that rewrite the agent's MCP config automatically.","Re-run setup after agent upgrades to refresh the journal."],"tags":["safety-interlock","removal","mcp","config-drift","cli"],"backgroundTag":"config-drift","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}