{"record":{"id":"de9882d06f54b2ef","repo":"JuliusBrussee/caveman","slug":"cave-slot-budget-exceeded","errorCode":"cave_${slot}_budget_exceeded","errorMessage":"cave_${slot}_budget_exceeded","messagePattern":"cave_(.+?)_budget_exceeded","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":2572,"sourceCode":"  }\n  return ordered;\n}\n\nexport function enforceSemanticBudgets(\n  bill: Readonly<Record<string, number>>,\n  outputMaxTokens: number,\n  plan: CavePlan,\n): void {\n  const slots: Array<[keyof CavePlan[\"budgets\"], number]> = [\n    [\"instructions\", bill.instruction ?? 0],\n    [\"tools\", bill.tool_schema ?? 0],\n    [\"memory\", bill.memory ?? 0],\n    [\"history\", bill.history ?? 0],\n    [\"results_artifacts\", (bill.artifact ?? 0) + (bill.skill ?? 0) + (bill.tool_result ?? 0)],\n    [\"output\", outputMaxTokens],\n  ];\n  for (const [slot, used] of slots) {\n    if (used > plan.budgets[slot]) throw new Error(`cave_${slot}_budget_exceeded`);\n  }\n}\n\nexport function assembleSystemPrompt(\n  definition: AgentDefinition,\n  lowered: LoweredContext,\n  bodies: ReadonlyMap<string, Uint8Array> = lowered.bodies,\n): string {\n  const decoder = new TextDecoder();\n  const required = [\"agent.instructions\", ...definition.contexts.map((item) => item.id)];\n  const parts: string[] = [];\n  for (const id of required) {\n    const segment = lowered.ir.segments.find((item) => item.id === id);\n    if (!segment) throw new Error(`cave_context_segment_missing:${id}`);\n    const body = bodies.get(segment.bodyHandle);\n    if (!body) throw new Error(`cave_context_body_missing:${id}`);\n    const text = decoder.decode(body);\n    parts.push(id === \"agent.instructions\" ? text : `<cave-context id=${JSON.stringify(id)}>\\n${text}\\n</cave-context>`);","sourceCodeStart":2554,"sourceCodeEnd":2590,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/runtime.ts#L2554-L2590","documentation":"Thrown by the budget-validation step of the Caveman agent runtime when a token bill for one prompt slot exceeds the allocation in the lowered plan (plan.budgets). The runtime splits the prompt into slots — memory, history, results_artifacts (artifact+skill+tool_result), and output — and enforces hard per-slot caps before assembling the request. It throws early with the slot name in the message so the caller knows which budget was blown.","triggerScenarios":"Calling the agent run path with a bill whose value for a slot (memory, history, artifact/skill/tool_result totals) exceeds plan.budgets[slot], or whose planned outputMaxTokens exceeds the output budget. Any single slot over its cap trips the check in the slot loop.","commonSituations":"Injecting an oversized memory blob or accumulated history without compaction; many tool results/artifacts accumulating in one turn; a plan configured with tight budgets while the context naturally grew; upgrading agents without revisiting budget allocations.","solutions":["Identify the slot named in the message (e.g. cave_history_budget_exceeded means history) and trim or compact that segment's content.","Raise the corresponding budgets[slot] value in the plan/agent definition to a realistic ceiling.","Enable or widen compaction/transform routes for the offending slot so content is reduced before budget validation.","Check for runaway growth (unbounded tool_result accumulation) and cap tool output or drop old results."],"exampleFix":"// before\nplan.budgets = { memory: 1000, history: 2000, results_artifacts: 2000, output: 1000 };\n// with a 3500-token history\n// after\nplan.budgets = { memory: 1000, history: 4000, results_artifacts: 2000, output: 1000 };\n// or compact history before the run","handlingStrategy":"validation","validationCode":"const slots = { memory: bill.memory ?? 0, history: bill.history ?? 0, results_artifacts: (bill.artifact ?? 0) + (bill.skill ?? 0) + (bill.tool_result ?? 0), output: outputMaxTokens };\nfor (const [slot, used] of Object.entries(slots)) {\n  if (used > plan.budgets[slot]) console.warn(`slot ${slot} over budget: ${used} > ${plan.budgets[slot]}`);\n}","typeGuard":"function withinBudget(used: number, budget: number | undefined): boolean { return typeof budget === \"number\" && used <= budget; }","tryCatchPattern":"try {\n  await agent.run(input);\n} catch (err) {\n  if (err instanceof Error && /^cave_[a-z_]+_budget_exceeded$/.test(err.message)) {\n    const slot = err.message.match(/^cave_([a-z_]+)_budget_exceeded$/)?.[1];\n    // compact that slot or raise plan.budgets[slot], then retry\n  } else throw err;\n}","preventionTips":["Track per-slot token usage after each turn and compact proactively before caps are hit.","Set budgets with headroom (e.g. 80% of the real limit you want enforced).","Cap tool_result sizes at the tool boundary so artifacts never dominate the bill.","Re-validate budgets whenever the agent definition or context sources change."],"tags":["budget","tokens","context-window","agent-runtime"],"backgroundTag":"value-out-of-range","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"}