JuliusBrussee/caveman · error · Error
Aider integration journal lacks owned blocks
Error message
Aider integration journal lacks owned blocks
What it means
The Aider integration journal (~/.caveman/integrations/aider.json) exists, but its owned metadata lacks route_block or read_block as strings — the exact config snippets Caveman inserted into ~/.aider.conf.yml at enable time. Without those strings the disable cannot surgically remove its own additions, so it aborts. In practice this means the journal was written by an older Caveman schema, was truncated, or was hand-edited.
Source
Thrown at packages/cli/src/index.ts:7693
const mcp = root.mcp && typeof root.mcp === "object" && !Array.isArray(root.mcp) ? root.mcp as Record<string, unknown> : {};
if (mcp.caveman !== undefined && JSON.stringify(mcp.caveman) !== JSON.stringify(operation.owned?.installed_mcp)) {
throw new Error("OpenCode caveman MCP entry changed after enable; refusing destructive disable");
}
if (mcp.caveman !== undefined) {
if (operation.owned?.previous_mcp === null || operation.owned?.previous_mcp === undefined) delete mcp.caveman;
else mcp.caveman = operation.owned.previous_mcp;
}
if (Object.keys(mcp).length > 0) root.mcp = mcp;
else delete root.mcp;
return jsonBytes(root);
}
if (operation.kind === "aider-config") {
let text = current.toString("utf8");
const routeBlock = operation.owned?.route_block;
const readBlock = operation.owned?.read_block;
const previousRouteLine = operation.owned?.previous_route_line;
if (typeof routeBlock !== "string" || typeof readBlock !== "string") {
throw new Error("Aider integration journal lacks owned blocks");
}
if (!text.includes(routeBlock) || !text.includes(readBlock)) {
throw new Error("Aider Caveman config block changed after enable; refusing destructive disable");
}
text = text.replace(routeBlock, typeof previousRouteLine === "string" ? previousRouteLine : "");
text = text.replace(readBlock, "");
return Buffer.from(text.replace(/\n{3,}/g, "\n\n"));
}
if (operation.kind === "aider-core") {
throw new Error(`${operation.file} changed after enable; refusing destructive disable`);
}
if (operation.kind === "hermes-plugin-manifest" || operation.kind === "hermes-plugin-init") {
throw new Error(`${operation.file} changed after enable; refusing destructive disable`);
}
if (operation.kind === "hermes-config") {
let text = current.toString("utf8");
const routeBlock = operation.owned?.route_block;
const previousRouteLines = operation.owned?.previous_route_lines;View on GitHub (pinned to 2f49f0e1a3)
Solutions
- Re-run `caveman enable aider` so a fresh, schema-current journal is written against the live config, then `caveman disable aider`
- Upgrade Caveman to the version that wrote the journal (the one used at enable time) and disable with it
- Manual cleanup: delete the Caveman-owned blocks from ~/.aider/conf.yml, then remove ~/.caveman/integrations/aider.json (and .pending-aider.json if present)
Example fix
# before: stale/partial journal blocks disable caveman disable aider # >> Aider integration journal lacks owned blocks # after: re-stamp journal then disable caveman enable aider && caveman disable aider
Defensive patterns
Strategy: validation
Validate before calling
// Validate journal shape before attempting disable
import { readFileSync } from 'node:fs';
const home = process.env.CAVEMAN_HOME ?? `${process.env.HOME}/.caveman`;
const j = JSON.parse(readFileSync(`${home}/integrations/aider.json`, 'utf8'));
const valid = j.operations.every((op) =>
op.kind !== 'aider-config' ||
(typeof op.owned?.route_block === 'string' && typeof op.owned?.read_block === 'string'));
if (!valid) console.error('journal pre-dates current schema — re-run `caveman enable aider` first'); Type guard
const hasAiderOwnedBlocks = (op) => typeof op.owned?.route_block === 'string' && typeof op.owned?.read_block === 'string';
Try / catch
catch (err) { if (err.message.includes('journal lacks owned blocks')) { /* run `caveman enable aider` to rewrite the journal, then disable */ } else throw err; } Prevention
- Disable integrations with the same caveman version that enabled them
- Do not hand-edit ~/.caveman/integrations/*.json
- After any caveman upgrade, run `caveman doctor <agent>` before scripting disables
When it happens
Trigger: `caveman disable aider` or `caveman doctor aider --fix` with a journal whose operations[].owned is missing/non-string route_block or read_block — typically after downgrading Caveman across a journal schema change, or after manually editing ~/.caveman/integrations/aider.json.
Common situations: Switching between Caveman versions (beta to stable and back); partial disk write or manual 'cleanup' of the integrations directory; copying a machine's ~/.caveman around with a partially copied journal.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Gemini integration journal lacks owned routing block
- Hermes integration journal lacks owned routing block
- Codex integration journal lacks owned blocks
- Aider Caveman config block changed after enable; refusing de
- cave_context_ir_invalid
AI-assisted analysis of JuliusBrussee/caveman@2f49f0e1a3 (2026-08-18).
Data as JSON: /api/errors/8a8194c96daf58ee.
Report an issue: GitHub.