{"record":{"id":"15a0f1b6ed7b5888","repo":"JuliusBrussee/caveman","slug":"cave-context-body-missing","errorCode":"cave_context_body_missing","errorMessage":"cave_context_body_missing:${segment.id}","messagePattern":"cave_context_body_missing:(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":854,"sourceCode":"      return \"run caveman login, then npm run build\";\n    case \"search_budget_exceeded\":\n      return \"raise maxSearchCostUsd or narrow allowed models, then run npm run build\";\n    case \"no_passing_build\":\n      return \"keep baseline and inspect failing eval evidence\";\n    case \"incomplete_evidence\":\n      return \"fix missing terminal usage or grader evidence, then run npm run build\";\n  }\n}\n\nasync function profilePreferredTransforms(\n  lowered: Awaited<ReturnType<typeof lowerContext>>,\n): Promise<ReadonlyMap<string, string>> {\n  const preferred = new Map<string, string>();\n  for (const segment of lowered.ir.segments) {\n    if (segment.safety !== \"S4\" ||\n        /(?:opaque|signed|signature|jwt|token|cipher|encrypted)/i.test(segment.id)) continue;\n    const body = lowered.bodies.get(segment.bodyHandle);\n    if (!body) throw new Error(`cave_context_body_missing:${segment.id}`);\n    const type = await detectEngineType(body);\n    if (/^[a-z0-9-]+$/.test(type) && type !== \"unknown\") {\n      preferred.set(segment.id, `caveman.engine.${type}.v1`);\n    }\n  }\n  return preferred;\n}\n\nasync function detectEngineType(input: Uint8Array): Promise<string> {\n  const command = process.env.CAVEMAN_ENGINE_BIN ?? \"caveman-engine\";\n  return new Promise((accept, reject) => {\n    const env = buildEngineEnv();\n    const invocation = portableInvocation(command, [\"detect\"], { env });\n    const child = spawn(invocation.command, [...invocation.args], {\n      env,\n      stdio: [\"pipe\", \"pipe\", \"pipe\"],\n    });\n    const stdout: Buffer[] = [];","sourceCodeStart":836,"sourceCodeEnd":872,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/cli.ts#L836-L872","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsegments: [{ id: \"instructions\", safety: \"S4\", bodyHandle: \"instr_v2\" }]\n// bodies: { \"instructions_body\": ... }   // mismatch\n// after\nsegments: [{ id: \"instructions\", safety: \"S4\", bodyHandle: \"instructions_body\" }]\n// bodies: { \"instructions_body\": ... }","handlingStrategy":"validation","validationCode":"// before build, verify every segment bodyHandle resolves\nfor (const seg of ir.segments) {\n  if (!bodies.has(seg.bodyHandle)) {\n    throw new Error(`segment ${seg.id} references missing body ${seg.bodyHandle}`);\n  }\n}","typeGuard":"const hasBody = (seg: Segment, bodies: Map<string, Body>): boolean => bodies.has(seg.bodyHandle);","tryCatchPattern":"try {\n  await build();\n} catch (err) {\n  const m = /^cave_context_body_missing:(.+)$/.exec(String(err?.message));\n  if (m) console.error(`Add/restore body for segment ${m[1]} and rebuild`);\n  throw err;\n}","preventionTips":["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."],"tags":["context-ir","invariant","build"],"backgroundTag":"internal-invariant-violation","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}