JuliusBrussee/caveman · error
cave_context_body_missing
cave_context_body_missing
Error message
cave_context_body_missing:${segment.id} What it means
When deriving preferred engines for the context IR, the CLI looks up each S4 safety segment's body via lowered.bodies.get(segment.bodyHandle). Segments whose ids look like opaque/signed/token/cipher material are skipped, but any other S4 segment whose body handle has no entry in the bodies map causes this coded error — the IR references a body that was never materialized.
Solutions
- Ensure every S4 segment's bodyHandle has a corresponding entry in the context bodies map.
- Regenerate/rebuild so the IR and bodies are produced together (npm run build).
- Check for typos or renames of the handle named in the error (segment id is appended to the message).
- Verify body source files exist and your loaders actually register them.
Example fix
// before
segments: [{ id: "instructions", safety: "S4", bodyHandle: "instr_v2" }]
// bodies: { "instructions_body": ... } // mismatch
// after
segments: [{ id: "instructions", safety: "S4", bodyHandle: "instructions_body" }]
// bodies: { "instructions_body": ... } Defensive patterns
Strategy: validation
Validate before calling
// before build, verify every segment bodyHandle resolves
for (const seg of ir.segments) {
if (!bodies.has(seg.bodyHandle)) {
throw new Error(`segment ${seg.id} references missing body ${seg.bodyHandle}`);
}
} Type guard
const hasBody = (seg: Segment, bodies: Map<string, Body>): boolean => bodies.has(seg.bodyHandle);
Try / catch
try {
await build();
} catch (err) {
const m = /^cave_context_body_missing:(.+)$/.exec(String(err?.message));
if (m) console.error(`Add/restore body for segment ${m[1]} and rebuild`);
throw err;
} Prevention
- Rename handles with search-and-replace across segments and bodies together.
- Regenerate IR and bodies in the same build step; never mix generations.
- Add a unit test asserting every S4 segment's handle exists in the bodies map.
- Don't delete body source files referenced by the context.
When it happens
Trigger: A lowered context IR segment (safety S4, non-opaque id) points at a bodyHandle absent from the bodies map — e.g. a context references a body file/handle that was never loaded, was renamed, or was dropped during lowering.
Common situations: Renaming a body/handle in the context definition without updating the reference; deleting a body source file; a custom loader failing silently so the body never enters the map; stale generated IR from an older build.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- adapter-specific build_sha256 values must differ
- agent conformance fixtures must cover claude and pi
- agent conformance mismatch
- cave_execution_plan_selection_mismatch
- cave_privacy_conformance_failed
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/15a0f1b6ed7b5888.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/cli.ts:854
return "run caveman login, then npm run build";
case "search_budget_exceeded":
return "raise maxSearchCostUsd or narrow allowed models, then run npm run build";
case "no_passing_build":
return "keep baseline and inspect failing eval evidence";
case "incomplete_evidence":
return "fix missing terminal usage or grader evidence, then run npm run build";
}
}
async function profilePreferredTransforms(
lowered: Awaited<ReturnType<typeof lowerContext>>,
): Promise<ReadonlyMap<string, string>> {
const preferred = new Map<string, string>();
for (const segment of lowered.ir.segments) {
if (segment.safety !== "S4" ||
/(?:opaque|signed|signature|jwt|token|cipher|encrypted)/i.test(segment.id)) continue;
const body = lowered.bodies.get(segment.bodyHandle);
if (!body) throw new Error(`cave_context_body_missing:${segment.id}`);
const type = await detectEngineType(body);
if (/^[a-z0-9-]+$/.test(type) && type !== "unknown") {
preferred.set(segment.id, `caveman.engine.${type}.v1`);
}
}
return preferred;
}
async function detectEngineType(input: Uint8Array): Promise<string> {
const command = process.env.CAVEMAN_ENGINE_BIN ?? "caveman-engine";
return new Promise((accept, reject) => {
const env = buildEngineEnv();
const invocation = portableInvocation(command, ["detect"], { env });
const child = spawn(invocation.command, [...invocation.args], {
env,
stdio: ["pipe", "pipe", "pipe"],
});
const stdout: Buffer[] = [];View on GitHub (pinned to 3ee70a1026)