JuliusBrussee/caveman · error

${skill.file} changed after setup; refusing destructive bund

Error message

${skill.file} changed after setup; refusing destructive bundle removal

What it means

Safety gate in removeAgentNativeBundle (--remove): before destructively uninstalling, each journaled skill file must still hash to after_sha256. If a skill file is missing or was modified since setup, removal aborts rather than overwrite/lose user changes layered on top of the installed skills.

Source

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

    throw new Error(`${agent} caveman-cloud MCP registration failed exact postflight`);
  }
  for (const skill of journal.skills) {
    const current = fileBytes(skill.file);
    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));

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. If you intentionally modified the skills, back them up, restore them to the installed content (or delete them knowingly), then re-run --remove
  2. Reinstall the bundle (`caveman setup --agent-native <agent>`) to reset skill files to journaled hashes, then immediately run --remove
  3. Locate the offending path from the error message and diff it against the installed version before deciding to discard changes
Defensive patterns

Strategy: validation

Validate before calling

// before --remove: verify journaled skills are unmodified
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
for (const skill of journal.skills) {
  let bytes: Buffer;
  try { bytes = readFileSync(skill.file); } catch { throw new Error(`${skill.file} missing; removal will abort`); }
  if (createHash("sha256").update(bytes).digest("hex") !== skill.after_sha256) {
    throw new Error(`${skill.file} modified; back it up or reinstall before --remove`);
  }
}

Try / catch

try {
  await setup(["--agent-native", agent, "--remove"]);
} catch (error) {
  if (/refusing destructive bundle removal/.test((error as Error).message) && /failed skill postflight|changed after setup/.test((error as Error).message)) {
    // back up the named file, reinstall bundle to reset hashes, then remove
    await backupAndReset(skillFileFromMessage(error));
    await setup(["--agent-native", agent, "--remove"]);
  } else throw error;
}

Prevention

When it happens

Trigger: Running `caveman setup --agent-native <agent> --remove` after a skill file in the journal was edited, deleted, or rewritten by the agent or the user.

Common situations: User customized an installed SKILL.md; the agent updated its own skill files; sync conflicts changed file contents since the bundle was installed.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/e55ae937fbc3f3c0. Report an issue: GitHub.