JuliusBrussee/caveman · error · Error

caveman-cloud MCP changed after setup; refusing destructive…

Error message

${agent} caveman-cloud MCP changed after setup; refusing destructive bundle removal

What it means

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.

Solutions

  1. 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.
  2. Re-run `caveman setup --agent-native <agent>` to refresh the journal's cloud_mcp record to current values, then --remove.
  3. Identify what rewrote the entry (agent update, another tool) and disable that rewriter before removing.
  4. If the current registration is intentionally different and you accept manual cleanup, remove the MCP entry and skill files by hand instead of --remove.

Example fix

// before: marker points at old node binary after upgrade
"caveman-cloud": { "command": "/usr/local/bin/node18" }
// after: refresh journal then remove
$ caveman setup --agent-native claude
$ caveman setup --agent-native claude --remove
Defensive patterns

Strategy: validation

Validate before calling

const marker = readMcpServerMarker(agent, "caveman-cloud");
if (!sameMcpCommand(marker, journal.cloud_mcp) || !agentNativeCloudMcpMatches(agent, journal.cloud_mcp)) {
  console.error("caveman-cloud entry drifted; refresh with setup before --remove");
}

Try / catch

try {
  removeAgentNativeBundle(agent);
} catch (err) {
  if (/MCP changed after setup/.test((err as Error).message)) {
    console.error("Re-run `caveman setup --agent-native " + agent + "` to refresh the journal, then remove");
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/9ea4397e141c7e33. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/index.ts:2934

    if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} failed skill postflight`);
  }
}

function removeAgentNativeBundle(agent: "claude" | "codex"): void {
  recoverPendingAgentNativeRemoval(agent);
  recoverPendingAgentNativeBundle(agent);
  const journal = readAgentNativeBundleJournal(agent);
  if (!journal) {
    process.stderr.write(`${mark("warn")} ${agent}: no agent-native bundle journal found\n`);
    return;
  }
  for (const skill of journal.skills) {
    const current = fileBytes(skill.file);
    if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} changed after setup; refusing destructive bundle removal`);
  }
  const marker = readMcpServerMarker(agent, "caveman-cloud");
  if (!sameMcpCommand(marker, journal.cloud_mcp) || !agentNativeCloudMcpMatches(agent, journal.cloud_mcp)) {
    throw new Error(`${agent} caveman-cloud MCP changed after setup; refusing destructive bundle removal`);
  }
  if (journal.native_owned) {
    const nativeJournal = readNativeJournal(agent);
    if (nativeJournal) {
      for (const operation of nativeJournal.operations) restoreNativeOperation(operation);
    }
  }
  atomicWriteFile(agentNativeBundleRemovalJournalPath(agent), Buffer.from(JSON.stringify(journal, null, 2) + "\n"));
  try {
    restoreAgentNativeBundleSkills(journal.skills);
    restoreAgentNativeCloudMcp(agent, journal.previous_cloud_mcp);
    if (journal.native_owned) disableNativeAgent(agent);
    unlinkSync(agentNativeBundleJournalPath(agent));
    unlinkSync(agentNativeBundleRemovalJournalPath(agent));
  } catch (error) {
    try {
      restoreInstalledAgentNativeBundle(agent, journal);
      unlinkSync(agentNativeBundleRemovalJournalPath(agent));

View on GitHub (pinned to 3ee70a1026)