JuliusBrussee/caveman · error
cave_context_body_missing:${segment.id}
Error message
cave_context_body_missing:${segment.id} What it means
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.
Source
Thrown at packages/agent/src/runtime.ts:2646
let recoveryResolved = true;
for (const route of plan.segment_routes) {
if (!known.has(route.transform_id)) {
throw new Error(`cave_unknown_transform:${route.transform_id}`);
}
const targets = lowered.ir.segments.filter((segment) =>
segment.kind === route.segment_kind &&
(route.segment_id === undefined || segment.id === route.segment_id));
if (targets.length === 0) {
if (route.segment_kind === "history" || route.segment_kind === "tool_result") {
continue;
}
throw new Error(`cave_plan_route_unmatched:${route.segment_id ?? route.segment_kind}`);
}
evaluated.push(route.transform_id);
let routeApplied = false;
for (const segment of targets) {
const original = lowered.bodies.get(segment.bodyHandle);
if (!original) throw new Error(`cave_context_body_missing:${segment.id}`);
if (segment.safety !== "S4") throw new Error(`cave_transform_safety_mismatch:${segment.id}`);
const startedAt = performance.now();
// beforeTokens/afterTokens are byte-derived (bytes/4) throughout so a
// delta is always within one basis. beforeTokens counts the ORIGINAL
// bytes; afterTokens, for an applied transform, counts the FULL provider
// body actually sent — wrapper included. segment.tokenCount
// is already estimateTokens(original) = bytes/4.
const beforeTokens = segment.tokenCount;
if (segment.opaque) {
trace.push({
segmentKind: segment.kind,
transformID: route.transform_id,
safetyClass: segment.safety,
beforeTokens,
afterTokens: beforeTokens,
tokensBasis: "byte_derived",
recoveryKind: segment.recovery,
recoveryUsed: false,View on GitHub (pinned to 27d5a3981a)
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
Defensive patterns
Strategy: validation
Validate before calling
function bodiesCoverTargets(plan: CavePlan, lowered: LoweredContext): boolean {
return lowered.ir.segments
.filter((s) => plan.segment_routes.some((r) =>
r.segment_kind === s.kind && (r.segment_id === undefined || r.segment_id === s.id)))
.every((s) => lowered.bodies.has(s.bodyHandle));
} Type guard
function isTransformBodyMissing(e: unknown): string | null {
if (!(e instanceof Error)) return null;
const m = /^cave_context_body_missing:(.+)$/.exec(e.message);
return m ? m[1] : null;
} Try / catch
if (!bodiesCoverTargets(plan, lowered)) {
lowered = await lowerContexts(definition);
}
await applyPlan(plan, lowered); Prevention
- 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
When it happens
Trigger: 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.
Common situations: Serializing/deserializing lowered contexts across process boundaries without the binary bodies; post-processing pipelines that drop bodies; lowering bugs.
Related errors
- cave_context_body_missing:${id}
- cave_harness_transform_not_evaluated
- cave_harness_unknown_transform
- cave_context_segment_missing:${id}
- cave_unknown_transform:${route.transform_id}
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/003b4e472759b440.
Report an issue: GitHub.