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

  1. Ensure every S4 segment's bodyHandle has a corresponding entry in the context bodies map.
  2. Regenerate/rebuild so the IR and bodies are produced together (npm run build).
  3. Check for typos or renames of the handle named in the error (segment id is appended to the message).
  4. 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

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


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)