{"record":{"id":"003b4e472759b440","repo":"JuliusBrussee/caveman","slug":"cave-context-body-missing-segment-id-003b4e","errorCode":null,"errorMessage":"cave_context_body_missing:${segment.id}","messagePattern":"cave_context_body_missing:(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":2646,"sourceCode":"  let recoveryResolved = true;\n  for (const route of plan.segment_routes) {\n    if (!known.has(route.transform_id)) {\n      throw new Error(`cave_unknown_transform:${route.transform_id}`);\n    }\n    const targets = lowered.ir.segments.filter((segment) =>\n      segment.kind === route.segment_kind &&\n      (route.segment_id === undefined || segment.id === route.segment_id));\n    if (targets.length === 0) {\n      if (route.segment_kind === \"history\" || route.segment_kind === \"tool_result\") {\n        continue;\n      }\n      throw new Error(`cave_plan_route_unmatched:${route.segment_id ?? route.segment_kind}`);\n    }\n    evaluated.push(route.transform_id);\n    let routeApplied = false;\n    for (const segment of targets) {\n      const original = lowered.bodies.get(segment.bodyHandle);\n      if (!original) throw new Error(`cave_context_body_missing:${segment.id}`);\n      if (segment.safety !== \"S4\") throw new Error(`cave_transform_safety_mismatch:${segment.id}`);\n      const startedAt = performance.now();\n      // beforeTokens/afterTokens are byte-derived (bytes/4) throughout so a\n      // delta is always within one basis. beforeTokens counts the ORIGINAL\n      // bytes; afterTokens, for an applied transform, counts the FULL provider\n      // body actually sent — wrapper included. segment.tokenCount\n      // is already estimateTokens(original) = bytes/4.\n      const beforeTokens = segment.tokenCount;\n      if (segment.opaque) {\n        trace.push({\n          segmentKind: segment.kind,\n          transformID: route.transform_id,\n          safetyClass: segment.safety,\n          beforeTokens,\n          afterTokens: beforeTokens,\n          tokensBasis: \"byte_derived\",\n          recoveryKind: segment.recovery,\n          recoveryUsed: false,","sourceCodeStart":2628,"sourceCodeEnd":2664,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/runtime.ts#L2628-L2664","documentation":"Thrown while applying transforms to segments matched by a route: the segment exists in the IR but lowered.bodies lacks bytes for its bodyHandle. Same root cause as cave_context_body_missing at prompt assembly, but hit on the transform path.","triggerScenarios":"A plan route matches segments whose bodyHandle is absent from lowered.bodies — e.g. bodies stripped after plan matching, a partially serialized LoweredContext, or a custom bodies override missing handles.","commonSituations":"Serializing/deserializing lowered contexts across process boundaries without the binary bodies; post-processing pipelines that drop bodies; lowering bugs.","solutions":["Re-lower the context to restore a complete bodies map before applying the plan","Ensure any bodies map passed alongside the plan contains all matched segments' handles","Check the segment id in the error to find which body went missing"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function bodiesCoverTargets(plan: CavePlan, lowered: LoweredContext): boolean {\n  return lowered.ir.segments\n    .filter((s) => plan.segment_routes.some((r) =>\n      r.segment_kind === s.kind && (r.segment_id === undefined || r.segment_id === s.id)))\n    .every((s) => lowered.bodies.has(s.bodyHandle));\n}","typeGuard":"function isTransformBodyMissing(e: unknown): string | null {\n  if (!(e instanceof Error)) return null;\n  const m = /^cave_context_body_missing:(.+)$/.exec(e.message);\n  return m ? m[1] : null;\n}","tryCatchPattern":"if (!bodiesCoverTargets(plan, lowered)) {\n  lowered = await lowerContexts(definition);\n}\nawait applyPlan(plan, lowered);","preventionTips":["Keep bodies and segments in one immutable lowered bundle","Don't filter bodies between lowering and plan application","Reproduce lowering in-process instead of shipping partial contexts across boundaries"],"tags":["transforms","bodies","lowering"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}