{"record":{"id":"1c90ecb758ec9e83","repo":"JuliusBrussee/caveman","slug":"agent-native-bundle-removal-failed-error-as-er","errorCode":null,"errorMessage":"agent-native bundle removal failed: ${(error as Error).message}; rollback incomplete: ${(rollback as Error).message}","messagePattern":"agent-native bundle removal failed: (.+?); rollback incomplete: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/index.ts","lineNumber":2954,"sourceCode":"  if (journal.native_owned) {\n    const nativeJournal = readNativeJournal(agent);\n    if (nativeJournal) {\n      for (const operation of nativeJournal.operations) restoreNativeOperation(operation);\n    }\n  }\n  atomicWriteFile(agentNativeBundleRemovalJournalPath(agent), Buffer.from(JSON.stringify(journal, null, 2) + \"\\n\"));\n  try {\n    restoreAgentNativeBundleSkills(journal.skills);\n    restoreAgentNativeCloudMcp(agent, journal.previous_cloud_mcp);\n    if (journal.native_owned) disableNativeAgent(agent);\n    unlinkSync(agentNativeBundleJournalPath(agent));\n    unlinkSync(agentNativeBundleRemovalJournalPath(agent));\n  } catch (error) {\n    try {\n      restoreInstalledAgentNativeBundle(agent, journal);\n      unlinkSync(agentNativeBundleRemovalJournalPath(agent));\n    } catch (rollback) {\n      throw new Error(`agent-native bundle removal failed: ${(error as Error).message}; rollback incomplete: ${(rollback as Error).message}`);\n    }\n    throw new Error(`agent-native bundle removal failed: ${(error as Error).message}; installed bundle restored`);\n  }\n  process.stderr.write(`${mark(\"ok\")} ${agent}: agent-native bundle removed; prior skills and cloud MCP restored\\n`);\n}\n\nasync function setup(argv: string[] = []) {\n  const json = argv.includes(\"--json\");\n  const install = argv.includes(\"--install\");\n  const removeBundle = argv.includes(\"--remove\");\n  const agentNative = flagFrom(argv, \"--agent-native\", \"\");\n  const hasAgentNativeFlag = argv.includes(\"--agent-native\") || argv.some((arg) => arg.startsWith(\"--agent-native=\"));\n  const unknown = argv.filter((arg, index) =>\n    arg !== \"--json\"\n    && arg !== \"--install\"\n    && arg !== \"--remove\"\n    && arg !== \"--agent-native\"\n    && !arg.startsWith(\"--agent-native=\")","sourceCodeStart":2936,"sourceCodeEnd":2972,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L2936-L2972","documentation":"Thrown when removing the agent-native bundle failed AND the attempt to restore the installed bundle from the journal also failed. The message chains the original removal error with the rollback error, telling the user the system is now in a partially removed state that automatic recovery could not fix.","triggerScenarios":"During `--remove`, an error occurs while tearing down the bundle, the catch block calls restoreInstalledAgentNativeBundle, and that restoration itself throws (e.g. missing journaled files, permission errors) — the rollback catch then throws this combined error.","commonSituations":"Skill/MCP files locked by a running agent or file-sync tool; permissions changed since setup; journal references files that no longer exist so restore cannot recreate them; disk full during restore.","solutions":["Close running claude/codex processes and stop file-sync tools, then retry `caveman setup --agent-native <agent> --remove`.","Read both error halves: fix the rollback error first (usually permissions or a missing journaled file), then retry removal.","Manually restore from the removal journal: re-create/re-list files per journal and delete agentNativeBundleRemovalJournalPath so the pending-removal recovery can run cleanly next time.","If unrecoverable, run setup again to rebuild a consistent bundle, then remove it cleanly."],"exampleFix":"// before: remove with agent running\n$ claude serve & caveman setup --agent-native claude --remove\nError: ... removal failed: EBUSY; rollback incomplete: EBUSY\n// after\n$ pkill -f claude\n$ caveman setup --agent-native claude --remove","handlingStrategy":"try-catch","validationCode":"// Pre-check writability of every journaled path before attempting removal\nconst allWritable = [journal.skills.map(s => s.file), journal.removes ?? []].flat()\n  .every(p => { try { accessSync(dirname(p), W_OK); return true; } catch { return false; } });\nif (!allWritable) console.error(\"Fix permissions before removing the bundle\");","typeGuard":null,"tryCatchPattern":"try {\n  removeAgentNativeBundle(agent);\n} catch (err) {\n  if (/rollback incomplete/.test((err as Error).message)) {\n    console.error(\"Manual recovery required; close agents/sync tools, fix permissions, then re-run --remove\");\n  }\n}","preventionTips":["Close running claude/codex processes before removal.","Pause file-sync tools watching the agent config directory.","Run removal as the same user who ran setup."],"tags":["rollback","removal","atomicity","cli"],"backgroundTag":"rollback-incomplete","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}