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

  1. Fix the root cause in the message (usually file permissions or a lock) and re-run `caveman setup --agent-native <agent> --remove`.
  2. Close agents/sync tools holding handles on the skill or MCP config files.
  3. Check that the user running the command owns the agent config directory (chown if setup ran as another user).
  4. 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

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


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)