JuliusBrussee/caveman · error

caveman-cloud MCP changed during interrupted setup…

Error message

${agent} caveman-cloud MCP changed during interrupted setup; refusing destructive recovery

What it means

When recovering an interrupted agent-native bundle setup, the CLI checks that the caveman-cloud MCP registration in the agent's native config matches one of the known states (the pending config, the previous config, or the committed config), or is covered by a marker. If the marker is unknown and the host registration matches none of them, someone or something changed the MCP entry outside the journal, so destructive recovery is refused.

Solutions

  1. Restore the caveman-cloud MCP entry in the agent config to the command recorded in pending.cloud_mcp or previous_cloud_mcp
  2. Delete the pending bundle journal if you accept the current MCP registration and want a clean re-setup
  3. Re-run setup so the interrupted bundle completes and the journal is consumed
Defensive patterns

Strategy: validation

Validate before calling

const marker = readMcpServerMarker(agent, 'caveman-cloud');
const reg = readAgentMcpConfig(agent).find(s => s.name === 'caveman-cloud');
if (reg && marker && !sameMcpCommand(reg, marker)) console.error('MCP entry diverged from marker; restore before setup.');

Try / catch

try {
  runSetup(agent);
} catch (e) {
  if (String(e.message).includes('MCP changed during interrupted setup')) {
    // restore the recorded cloud_mcp command or delete the pending journal deliberately
  }
}

Prevention

When it happens

Trigger: Re-running setup after an interrupted run where the agent's native MCP config entry for caveman-cloud was edited manually, replaced by another installer, or the journal's marker file was deleted/does not match.

Common situations: User hand-edited claude_desktop_config.json / codex config.toml; another tool reinstalled the MCP server with a different command; a partially applied update changed the server command line.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

    const currentMatchesBefore = current === null ? before === null : before !== null && bytesHash(current) === bytesHash(before);
    const currentHash = current ? bytesHash(current) : null;
    const currentMatchesCommitted = currentHash !== null && currentHash === committedSkills.get(skill.file);
    if (!currentMatchesBefore && !currentMatchesCommitted && currentHash !== skill.after_sha256) {
      throw new Error(`${skill.file} changed during interrupted setup; refusing destructive recovery`);
    }
  }
  const marker = readMcpServerMarker(agent, "caveman-cloud");
  const markerKnown = !marker
    || sameMcpCommand(marker, pending.cloud_mcp)
    || sameMcpCommand(marker, pending.previous_cloud_mcp)
    || sameMcpCommand(marker, committed?.cloud_mcp ?? null);
  const hostInstalled = agentNativeCloudMcpMatches(agent, pending.cloud_mcp);
  const hostPrevious = pending.previous_cloud_mcp
    ? agentNativeCloudMcpMatches(agent, pending.previous_cloud_mcp)
    : agentNativeCloudMcpHostAbsent(agent);
  const hostCommitted = committed ? agentNativeCloudMcpMatches(agent, committed.cloud_mcp) : false;
  if (!markerKnown || (!hostInstalled && !hostPrevious && !hostCommitted)) {
    throw new Error(`${agent} caveman-cloud MCP changed during interrupted setup; refusing destructive recovery`);
  }
  restoreInstalledAgentNativeBundle(agent, pending);
  unlinkSync(agentNativeBundleJournalPath(agent, true));
  process.stderr.write(`${mark("warn")} completed interrupted ${agent} agent-native bundle before continuing\n`);
}

function skillMatchesBefore(skill: AgentNativeBundleSkill): boolean {
  const current = fileBytes(skill.file);
  const before = skill.before_base64 === null ? null : Buffer.from(skill.before_base64, "base64");
  return current === null ? before === null : before !== null && current.equals(before);
}

function agentNativeCloudMcpHostAbsent(agent: "claude" | "codex"): boolean {
  if (agent === "claude") return !claudeMcpRegistration("caveman-cloud").present;
  const config = fileBytes(join(codexHomeDir(), "config.toml"))?.toString("utf8") ?? "";
  return !config.includes("[mcp_servers.caveman-cloud]");
}

View on GitHub (pinned to 3ee70a1026)