JuliusBrussee/caveman · error · Error
Codex integration journal lacks owned blocks
Error message
Codex integration journal lacks owned blocks
What it means
The Codex integration journal (~/.caveman/integrations/codex.json) has a codex-config (TOML) operation whose owned metadata lacks root_block or tables_block as strings — the exact config.toml snippets Caveman inserted between its '# >>> caveman:native-root' / '# >>> caveman:native-tables' markers. Without them the disable cannot excise its own additions from ~/.codex/config.toml, so it aborts. Cause: journal written by an older schema, truncated, or hand-edited.
Source
Thrown at packages/cli/src/index.ts:7727
let text = current.toString("utf8");
const routeBlock = operation.owned?.route_block;
const previousRouteLines = operation.owned?.previous_route_lines;
if (typeof routeBlock !== "string" || !Array.isArray(previousRouteLines)) {
throw new Error("Hermes integration journal lacks owned routing block");
}
if (!text.includes(routeBlock)) throw new Error("Hermes routing block changed after enable; refusing destructive disable");
text = text.replace(routeBlock, previousRouteLines.filter((line): line is string => typeof line === "string").join("\n"));
for (const key of ["plugin_block", "mcp_block"] as const) {
const block = operation.owned?.[key];
if (block === null || block === undefined) continue;
if (typeof block !== "string" || !text.includes(block)) throw new Error(`Hermes ${key.replace("_block", "")} block changed after enable; refusing destructive disable`);
text = text.replace(block, "");
}
return Buffer.from(text);
}
const rootBlock = operation.owned?.root_block;
const tablesBlock = operation.owned?.tables_block;
if (typeof rootBlock !== "string" || typeof tablesBlock !== "string") throw new Error("Codex integration journal lacks owned blocks");
let text = current.toString("utf8");
for (const [block, begin] of [[rootBlock, CODEX_NATIVE_ROOT_BEGIN], [tablesBlock, CODEX_NATIVE_TABLES_BEGIN]] as const) {
if (text.includes(begin) && !text.includes(block)) throw new Error("Codex Caveman config block changed after enable; refusing destructive disable");
text = text.replace(`${block}\n\n`, "").replace(`\n\n${block}\n`, "\n").replace(block, "");
}
return Buffer.from(text);
}
function writeNativeRestoration(file: string, bytes: Buffer | null): void {
if (bytes) {
atomicWriteFile(file, bytes);
return;
}
try { unlinkSync(file); } catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
View on GitHub (pinned to 2f49f0e1a3)
Solutions
- Re-run `caveman enable codex` to write a schema-current journal over the live config, then `caveman disable codex`
- Use the Caveman version that performed the enable to run the disable
- Manual path: delete everything between (and including) the caveman marker comments in ~/.codex/config.toml, then remove the journal
Example fix
# before: journal lacks owned blocks caveman disable codex # >> Codex integration journal lacks owned blocks # after: re-stamp then disable caveman enable codex && caveman disable codex
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
const home = process.env.CAVEMAN_HOME ?? `${process.env.HOME}/.caveman`;
const j = JSON.parse(readFileSync(`${home}/integrations/codex.json`, 'utf8'));
const bad = j.operations.filter((op) =>
typeof op.owned?.root_block !== 'string' || typeof op.owned?.tables_block !== 'string');
if (bad.length) console.error('journal pre-dates current schema — `caveman enable codex` rewrites it'); Type guard
const hasCodexOwnedBlocks = (op) => typeof op.owned?.root_block === 'string' && typeof op.owned?.tables_block === 'string';
Try / catch
catch (err) { if (err.message.includes('journal lacks owned blocks')) { /* `caveman enable codex && caveman disable codex` */ } else throw err; } Prevention
- Keep ~/.caveman/integrations/*.json untouched by cleanup scripts
- Match enable/disable caveman versions; run doctor after upgrades
When it happens
Trigger: `caveman disable codex` or `caveman doctor codex --fix` with a journal whose operations[].owned.root_block / tables_block are missing or non-string — typically after a Caveman version change or manual journal tampering.
Common situations: Downgrading Caveman across a journal schema change; a crashed enable; cleaning up ~/.caveman by hand and corrupting the JSON.
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
- Aider integration journal lacks owned blocks
- Hermes integration journal lacks owned routing block
- Codex 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/903237a709d5f9c4.
Report an issue: GitHub.