JuliusBrussee/caveman · error · Error
${operation.file} was removed after enable; refusing destruc
Error message
${operation.file} was removed after enable; refusing destructive disable What it means
restoreNativeOperation() refuses when a journaled file (before_exists true - it existed before enable) is now missing from disk. Caveman's own writes only replace files, never delete them, so a vanished file means something outside the transaction removed it; disable halts rather than guess whether recreating it is wanted.
Source
Thrown at packages/cli/src/index.ts:7559
}
}
const kept = list.filter((entry) => !expectedStrings.has(JSON.stringify(entry)));
if (kept.length > 0) hooks[event] = kept;
else delete hooks[event];
}
if (Object.keys(hooks).length === 0) delete root.hooks;
return root;
}
function jsonBytes(root: Record<string, unknown>): Buffer {
return Buffer.from(JSON.stringify(root, null, 2) + "\n");
}
function restoreNativeOperation(operation: NativeJournal["operations"][number]): Buffer | null {
const current = fileBytes(operation.file);
const before = nativeBackupBytes(operation);
if (!current) {
if (operation.before_exists) throw new Error(`${operation.file} was removed after enable; refusing destructive disable`);
return null;
}
if (bytesHash(current) === operation.after_sha256) return before;
if (operation.kind === "claude-settings") {
const currentRoot = parseJsonFileObject(operation.file, current);
const beforeRoot = parseJsonFileObject(operation.file, before);
const currentEnv = currentRoot.env && typeof currentRoot.env === "object" && !Array.isArray(currentRoot.env)
? currentRoot.env as Record<string, unknown>
: {};
const beforeEnv = beforeRoot.env && typeof beforeRoot.env === "object" && !Array.isArray(beforeRoot.env)
? beforeRoot.env as Record<string, unknown>
: {};
const route = operation.owned?.route;
if (currentEnv.ANTHROPIC_BASE_URL !== undefined && currentEnv.ANTHROPIC_BASE_URL !== route) {
throw new Error("Claude ANTHROPIC_BASE_URL changed after enable; refusing destructive disable");
}
if (currentEnv.ANTHROPIC_BASE_URL === route) {View on GitHub (pinned to 2f49f0e1a3)
Solutions
- Recreate the file, then re-run disable. The simplest source is the journal backup: the error names the file path, and the matching bytes are in ~/.caveman/integrations/backups/<agent>/<uuid>/<i>.bin.
- Or restore the file from your own dotfile backup.
- Run `caveman doctor <agent>` first - its checks table shows present:false for the missing file and names the journal entries involved.
Example fix
// before $ caveman disable claude Error: ~/.claude/settings.json was removed after enable; refusing destructive disable // after $ cp ~/.caveman/integrations/backups/claude/<uuid>/0.bin ~/.claude/settings.json $ caveman disable claude
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
const journal = JSON.parse(readFileSync(`${process.env.HOME}/.caveman/integrations/claude.json`, 'utf8'));
for (const op of journal.operations) {
if (op.before_exists) {
try { readFileSync(op.file); } catch { console.error(`${op.file} is missing; recreate it before 'caveman disable claude'`); process.exit(1); }
}
} Prevention
- Do not delete or rename journaled agent config files while an integration is enabled
- Keep dotfile backups of every file caveman enable reports writing
- Run `caveman doctor <agent>` after agents reset their own configs
When it happens
Trigger: `caveman disable <agent>` after the journaled config file (e.g. ~/.claude/settings.json or the codex config.toml named in the journal) was deleted, moved, or renamed by the user, a cleaner, or another tool.
Common situations: Switching configs by renaming (settings.json.dev); the agent resetting its own config on startup; cleanup scripts or dotfile managers removing 'unknown' files.
Related errors
- ${agent} ${event} Caveman hook changed after enable; refusin
- Claude ANTHROPIC_BASE_URL changed after enable; refusing des
- Claude caveman MCP entry changed after enable; refusing dest
- Gemini caveman MCP entry changed after enable; refusing dest
- Gemini routing block changed after enable; refusing destruct
AI-assisted analysis of JuliusBrussee/caveman@2f49f0e1a3 (2026-08-18).
Data as JSON: /api/errors/b8d4c363b3bd2d2f.
Report an issue: GitHub.