JuliusBrussee/caveman · error · Error
changed after setup; refusing to overwrite user skill edits
Error message
${file} changed after setup; refusing to overwrite user skill edits What it means
When a journaled bundle already exists, the CLI allows overwriting a skill file only if it matches the canonical body or still matches the previous bundle's recorded after_sha256 (i.e. Caveman content). If the file differs from both, the user modified the installed skill, and re-installing would destroy those edits, so it throws.
Solutions
- Back up your edits, then restore the file to the previously installed content and re-run setup
- Copy your customizations into a separate user-level skill path that Caveman does not manage
- Accept losing edits by deleting the old journal entry's claim (re-initialize the bundle) — only if edits are disposable
Example fix
// before
throw new Error(`${file} changed after setup; refusing to overwrite user skill edits`);
// after
// keep the user's version and skip reinstalling that skill:
copyFileSync(file, `${file}.user`); // preserve, then decide manually Defensive patterns
Strategy: validation
Validate before calling
const prev = existingBundle.skills.find(s => s.file === file);
const cur = readFileSync(file);
const userEdited = !cur.equals(Buffer.from(body)) &&
(!prev || createHash('sha256').update(cur).digest('hex') !== prev.after_sha256);
if (userEdited) console.error(`${file} has local edits; back them up before re-running setup.`); Try / catch
try {
runSetup(agent);
} catch (e) {
if (String(e.message).includes('refusing to overwrite user skill edits')) {
// copy your edited file aside, restore or accept the canonical version, retry
}
} Prevention
- Keep customizations in a separate user skill location, not in managed files
- Diff managed files against canonical before re-running setup
- Use git to track local edits so they can be reapplied after updates
When it happens
Trigger: Re-running setup with an existing bundle journal where a skill file's current bytes differ from the new canonical body AND from the previous journal entry's after_sha256 hash.
Common situations: User customized a Caveman-managed skill file (tweaked prompts) and later re-runs setup/update; a merge or code-review tool modified installed skills.
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
- already exists with non-canonical content; refusing to…
- changed during interrupted removal; refusing destructive…
- changed during interrupted setup; refusing destructive…
- caveman-cloud MCP changed after setup; refusing destructive…
- caveman-cloud MCP changed during interrupted setup…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/f525adfcb2ea5ef4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2870
if (status.state !== "installed") repairNativeAgent(agent);
}
function preflightAgentNativeBundleComponents(
agent: "claude" | "codex",
existingBundle: AgentNativeBundleJournal | null,
): void {
const previousSkills = new Map(existingBundle?.skills.map((skill) => [skill.file, skill]) ?? []);
for (const { file, body } of agentNativeSkillFiles(agent)) {
const current = fileBytes(file);
if (!existingBundle) {
if (current && !current.equals(Buffer.from(body))) {
throw new Error(`${file} already exists with non-canonical content; refusing to overwrite an unjournaled skill`);
}
continue;
}
const previous = previousSkills.get(file);
if (current && !current.equals(Buffer.from(body)) && (!previous || bytesHash(current) !== previous.after_sha256)) {
throw new Error(`${file} changed after setup; refusing to overwrite user skill edits`);
}
}
if (agent === "claude") {
const actual = claudeMcpRegistration("caveman-cloud");
const marker = readMcpServerMarker("claude", "caveman-cloud");
if (actual.present && !marker) {
throw new Error("Claude caveman-cloud MCP exists but is not Caveman-journaled; refusing overwrite");
}
if (actual.present && marker && !agentNativeCloudMcpMatches("claude", marker)) {
throw new Error("Claude caveman-cloud MCP changed after setup; refusing to overwrite user fields");
}
return;
}
const config = fileBytes(join(codexHomeDir(), "config.toml"))?.toString("utf8") ?? "";
if (!config.includes("[mcp_servers.caveman-cloud]")) return;
if (!readMcpServerMarker("codex", "caveman-cloud")) {
throw new Error("[mcp_servers.caveman-cloud] exists but is not Caveman-journaled; refusing overwrite");
}View on GitHub (pinned to 3ee70a1026)