JuliusBrussee/caveman · error · Error
changed after setup; refusing destructive bundle removal
Error message
${skill.file} changed after setup; refusing destructive bundle removal What it means
Thrown by removeAgentNativeBundle as a safety interlock: before destructively removing the agent-native bundle, every journaled skill file is re-hashed. If any file is missing or its hash differs from the journal's after_sha256, removal aborts because the bundle's contents were modified after setup and rollback/restore could destroy user changes.
Solutions
- If the edits are intentional, back them up, run --remove (or restore originals), then re-apply changes to a non-managed location.
- Restore the skill files to their setup-time content so hashes match the journal, then re-run --remove.
- Delete the stale journal (agent-native bundle journal path) only if you accept that the bundle will not be auto-rolled back, and remove files manually.
- Re-run setup to refresh the journal hashes to the current file contents, then remove.
Example fix
// before: removing with locally edited skill $ caveman setup --agent-native claude --remove Error: .../SKILL.md changed after setup; refusing destructive bundle removal // after: preserve the edit first $ cp ~/.claude/skills/caveman/SKILL.md ~/backup/SKILL.md $ git -C ~/.claude/skills/caveman checkout -- SKILL.md $ caveman setup --agent-native claude --remove
Defensive patterns
Strategy: validation
Validate before calling
for (const skill of journal.skills) {
const current = fileBytes(skill.file);
if (!current || bytesHash(current) !== skill.after_sha256) {
console.error(`Back up changes to ${skill.file} before running --remove`);
}
} Try / catch
try {
removeAgentNativeBundle(agent);
} catch (err) {
if (/changed after setup/.test((err as Error).message)) {
console.error("Bundle files were customized; back them up, then re-run --remove");
}
} Prevention
- Treat bundle-delivered skill files as managed: don't edit them in place.
- Keep local customizations in a separate, non-managed location.
- Re-run setup (refreshing journal hashes) after intentional edits, then remove.
When it happens
Trigger: Running `caveman setup --agent-native <agent> --remove` when a skill file delivered by the bundle has been edited, deleted, or replaced since setup — fileBytes returns null or the hash differs from journal.skills[].after_sha256.
Common situations: User customized a delivered skill file; a sync tool or editor rewrote the file; agent upgrade changed skill contents; manual cleanup deleted a skill file.
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
- caveman-cloud MCP changed after setup; refusing destructive…
- failed skill postflight
- agent-native bundle removal failed
- agent-native bundle removal failed
- caveman-cloud MCP changed during interrupted setup…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/e55ae937fbc3f3c0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2930
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 3ee70a1026)