JuliusBrussee/caveman · error · Error
agent-native bundle removal failed
Error message
agent-native bundle removal failed: ${(error as Error).message}; installed bundle restored What it means
Thrown when agent-native bundle removal failed but the rollback succeeded: restoreInstalledAgentNativeBundle re-created the previously installed bundle and the removal journal was deleted. The original failure is preserved in the message; the key reassurance is that the installed bundle is intact.
Solutions
- Fix the root cause in the message (usually file permissions or a lock) and re-run `caveman setup --agent-native <agent> --remove`.
- Close agents/sync tools holding handles on the skill or MCP config files.
- Check that the user running the command owns the agent config directory (chown if setup ran as another user).
- If the cause was a transient lock, retry immediately — the bundle was restored, so state is consistent.
Example fix
// before: root-owned skill file blocks removal Error: .../SKILL.md: EACCES; installed bundle restored // after $ sudo chown -R $(whoami) ~/.claude/skills/caveman $ caveman setup --agent-native claude --remove
Defensive patterns
Strategy: try-catch
Validate before calling
try { accessSync(agentConfigDir, W_OK); } catch {
console.error("Agent config dir not writable by current user; fix ownership before --remove");
} Try / catch
try {
removeAgentNativeBundle(agent);
} catch (err) {
if (/installed bundle restored/.test((err as Error).message)) {
console.error(`Removal failed but state is consistent: ${(err as Error).message}. Fix cause and retry.`);
}
} Prevention
- Keep ownership of the agent config directory consistent with the user running caveman.
- Retry after transient locks clear — rollback leaves state consistent.
- Check root-cause errno (EACCES/EBUSY) before retrying.
When it happens
Trigger: Any failure during the destructive phase of `--remove` (unlink/restore of prior skills, MCP restore, journal ops) that is NOT itself a rollback failure — the catch runs restoreInstalledAgentNativeBundle successfully and throws this message with the original error.
Common situations: Permission denied deleting a skill file; the removal journal's restore step hit a missing file; a process held an open handle on a journaled file; read-only filesystem.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- agent-native bundle removal failed
- agent-native setup failed
- caveman-cloud MCP changed after setup; refusing destructive…
- changed after setup; refusing destructive bundle removal
- caveman-cloud MCP changed during interrupted setup…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/bcaaea94f108f5bf.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2956
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));
} catch (error) {
try {
restoreInstalledAgentNativeBundle(agent, journal);
unlinkSync(agentNativeBundleRemovalJournalPath(agent));
} catch (rollback) {
throw new Error(`agent-native bundle removal failed: ${(error as Error).message}; rollback incomplete: ${(rollback as Error).message}`);
}
throw new Error(`agent-native bundle removal failed: ${(error as Error).message}; installed bundle restored`);
}
process.stderr.write(`${mark("ok")} ${agent}: agent-native bundle removed; prior skills and cloud MCP restored\n`);
}
async function setup(argv: string[] = []) {
const json = argv.includes("--json");
const install = argv.includes("--install");
const removeBundle = argv.includes("--remove");
const agentNative = flagFrom(argv, "--agent-native", "");
const hasAgentNativeFlag = argv.includes("--agent-native") || argv.some((arg) => arg.startsWith("--agent-native="));
const unknown = argv.filter((arg, index) =>
arg !== "--json"
&& arg !== "--install"
&& arg !== "--remove"
&& arg !== "--agent-native"
&& !arg.startsWith("--agent-native=")
&& argv[index - 1] !== "--agent-native");
if (unknown.length > 0 || (hasAgentNativeFlag && !agentNative) || (agentNative && (json || install)) || (removeBundle && !agentNative)) {View on GitHub (pinned to 3ee70a1026)