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

  1. Re-run `caveman enable aider` so a fresh, schema-current journal is written against the live config, then `caveman disable aider`
  2. Upgrade Caveman to the version that wrote the journal (the one used at enable time) and disable with it
  3. 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

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


AI-assisted analysis of JuliusBrussee/caveman@2f49f0e1a3 (2026-08-18). Data as JSON: /api/errors/8a8194c96daf58ee. Report an issue: GitHub.