JuliusBrussee/caveman · error

cave_context_body_missing:${id}

Error message

cave_context_body_missing:${id}

What it means

Thrown by assembleSystemPrompt when the segment exists in lowered.ir.segments but its bodyHandle has no entry in the bodies map. The segment metadata and the body bytes are carried separately; this error means metadata arrived without content.

Source

Thrown at packages/agent/src/runtime.ts:2588

  ];
  for (const [slot, used] of slots) {
    if (used > plan.budgets[slot]) throw new Error(`cave_${slot}_budget_exceeded`);
  }
}

export function assembleSystemPrompt(
  definition: AgentDefinition,
  lowered: LoweredContext,
  bodies: ReadonlyMap<string, Uint8Array> = lowered.bodies,
): string {
  const decoder = new TextDecoder();
  const required = ["agent.instructions", ...definition.contexts.map((item) => item.id)];
  const parts: string[] = [];
  for (const id of required) {
    const segment = lowered.ir.segments.find((item) => item.id === id);
    if (!segment) throw new Error(`cave_context_segment_missing:${id}`);
    const body = bodies.get(segment.bodyHandle);
    if (!body) throw new Error(`cave_context_body_missing:${id}`);
    const text = decoder.decode(body);
    parts.push(id === "agent.instructions" ? text : `<cave-context id=${JSON.stringify(id)}>\n${text}\n</cave-context>`);
  }
  if (definition.output) {
    parts.push(`<cave-output max_tokens=${definition.output.maxTokens}>Return output matching declared schema when present.</cave-output>`);
  }
  if (definition.memory) {
    parts.push("<cave-memory>Use cave_memory_search before relying on prior-session facts. Use cave_memory_remember only for durable facts the user intended to retain.</cave-memory>");
  }
  return parts.join("\n\n");
}

async function applyEfficiencyPlan(
  lowered: LoweredContext,
  plan: CavePlan | undefined,
  engineBin: string | undefined,
  signal?: AbortSignal,
): Promise<AppliedPlan> {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. If passing the optional bodies parameter, ensure it contains every bodyHandle referenced by ir.segments
  2. Re-lower the context to rebuild a consistent (segments, bodies) pair
  3. Audit any post-lowering transformation that filters or replaces bodies
Defensive patterns

Strategy: validation

Validate before calling

function allBodiesPresent(lowered: LoweredContext, bodies = lowered.bodies): boolean {
  return lowered.ir.segments.every((s) => bodies.has(s.bodyHandle));
}

Type guard

function isContextBodyMissing(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 (!allBodiesPresent(lowered)) {
  lowered = await lowerContexts(definition);
}
await assembleSystemPrompt(definition, lowered);

Prevention

When it happens

Trigger: lowered.bodies is missing the Uint8Array for a segment's bodyHandle — e.g. bodies were filtered, serialized/deserialized losing binary payloads, or a custom bodies map was passed (the third parameter overrides lowered.bodies) without all handles.

Common situations: Passing a custom bodies map (e.g. a transformed or cached copy) that omits handles; cloning/serializing LoweredContext and dropping the bodies map; a lowering bug that registered a handle but never stored bytes.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/5d65ee48e2271c48. Report an issue: GitHub.