JuliusBrussee/caveman · error
cannot read agent-native bundle journal
Error message
cannot read ${agent} agent-native bundle journal: ${(error as Error).message} What it means
Reading the agent-native bundle journal (a JSON file recording which cloud MCP/skills were installed for 'claude' or 'codex') failed with an error other than ENOENT (missing file, which returns null). The installer wraps the underlying error message and rethrows so the user knows journal state is unreadable.
Solutions
- Delete the corrupt journal file so the CLI can recreate it (it treats absence as null).
- Check file permissions/ownership on the journal path (fix with chmod/chown).
- Inspect the file to confirm valid JSON with schema_version 1 and correct 'agent' field.
- Reinstall/upgrade the CLI so journal schema matches the current version.
Example fix
// before cat ~/.caveman/claude-bundle.json // corrupt JSON // after rm ~/.caveman/claude-bundle.json && caveman install // recreates journal
Defensive patterns
Strategy: try-catch
Validate before calling
const p = journalPath(agent);
try { JSON.parse(readFileSync(p, 'utf8')); } catch { console.warn(`journal ${p} corrupt — delete it before installing`); } Type guard
function isJournal(v: unknown): v is AgentNativeBundleJournal {
return typeof v === 'object' && v !== null && (v as any).schema_version === 1 &&
typeof (v as any).agent === 'string' && Array.isArray((v as any).skills);
} Try / catch
try { await cavemanInstall() } catch (e) { if (String(e.message).includes('cannot read') && String(e.message).includes('journal')) { fs.rmSync(journalPath, { force: true }); await cavemanInstall(); } } Prevention
- Don't hand-edit journal files; let the CLI manage them.
- Avoid killing the CLI mid-install, which can truncate journals.
- Keep consistent user/UID so file permissions stay valid.
- Upgrade the CLI and let it migrate journal schemas.
When it happens
Trigger: readAgentNativeBundleJournal(agent) catches a non-ENOENT error from readFileSync/JSON.parse/schema validation of the journal file: EACCES/EISDIR on the journal path, invalid JSON, or schema_version !== 1 / wrong agent field / missing cloud_mcp or skills array.
Common situations: Journal file corrupted by a crash mid-write; file permissions changed after a user/UID switch; journal written by an older CLI with a different schema_version; journal path is a directory.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- cannot read pending agent-native bundle journal
- cannot read pending agent-native removal journal
- cannot read pending transaction
- caveman agent: invalid .caveman/provider.json
- integration journal disappeared during repair
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/d50cdd801514f10f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2581
function agentNativeBundleJournalPath(agent: "claude" | "codex", pending = false): string {
return join(cavemanHome(), "integrations", `${agent}.agent-native-bundle${pending ? ".pending" : ""}.json`);
}
function agentNativeBundleRemovalJournalPath(agent: "claude" | "codex"): string {
return join(cavemanHome(), "integrations", `${agent}.agent-native-bundle.removing.json`);
}
function readAgentNativeBundleJournal(agent: "claude" | "codex"): AgentNativeBundleJournal | null {
try {
const value = JSON.parse(readFileSync(agentNativeBundleJournalPath(agent), "utf8")) as AgentNativeBundleJournal;
if (value.schema_version !== 1 || value.agent !== agent || !value.cloud_mcp || !Array.isArray(value.skills)) {
throw new Error("unsupported bundle journal");
}
return value;
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
throw new Error(`cannot read ${agent} agent-native bundle journal: ${(error as Error).message}`);
}
}
function readPendingAgentNativeBundleJournal(agent: "claude" | "codex"): AgentNativeBundleJournal | null {
try {
const value = JSON.parse(readFileSync(agentNativeBundleJournalPath(agent, true), "utf8")) as AgentNativeBundleJournal;
if (value.schema_version !== 1 || value.agent !== agent || !value.cloud_mcp || !Array.isArray(value.skills)) {
throw new Error("unsupported pending bundle journal");
}
return value;
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
throw new Error(`cannot read pending ${agent} agent-native bundle journal: ${(error as Error).message}`);
}
}
function readPendingAgentNativeBundleRemoval(agent: "claude" | "codex"): AgentNativeBundleJournal | null {
try {View on GitHub (pinned to 3ee70a1026)