JuliusBrussee/caveman · error
cave_subagent_cost_budget
cave_subagent_cost_budget
Error message
cave_subagent_cost_budget
What it means
After the child settles, the tool's SpendLedger is re-checked: if it is flagged incomplete, or its actualUsd (catalog-priced dollars really spent by the child and its descendants) exceeds runtime.maxCostUsd, the parent aborts. The child exceeded its wallet, or an unpriced call inside the child poisoned the ledger; either way the cap is enforced terminally rather than silently exceeded.
Source
Thrown at packages/agent/src/runtime.ts:4062
throw new Error("cave_nested_usage_incomplete");
}
usage.inputTokens += child.inputTokens;
usage.outputTokens += child.outputTokens;
usage.cacheReadTokens += child.cacheReadTokens;
usage.cacheWriteTokens += child.cacheWriteTokens;
usage.reasoningTokens += child.reasoningTokens;
usage.costUsd += child.costUsd;
usage.receipts.push(child.receipt);
if (child.mode === "observe-only") usage.observeOnly = true;
if (child.priceBasis !== "public_catalog") usage.unpriced = true;
if (child.inputTokens > runtime.maxContextTokens) {
usage.incomplete = true;
throw new Error("cave_subagent_context_budget");
}
if (spendLedger !== undefined &&
(spendLedger.incomplete || spendLedger.actualUsd > runtime.maxCostUsd)) {
usage.incomplete = true;
throw new Error("cave_subagent_cost_budget");
}
return {
text: child.text,
agent_id: child.agentId,
usage_basis: child.usageBasis,
input_tokens: child.inputTokens,
output_tokens: child.outputTokens,
cost_usd: child.costUsd,
// A child that ran out of wallet returns partial work; the caller sees why
// rather than reading a truncated answer as a complete one.
stop_reason: child.stopReason,
claim_basis: "inferred",
};
}
function completeUsage(result: RunResult): boolean {
if (result.reasoningUsageBasis !== "provider_reported") return false;
return [View on GitHub (pinned to 766dce6b13)
Solutions
- Raise the subagent's maxCostUsd with headroom (the carve at spawn must still fit the parent's remaining budget)
- Shrink the child's task or limit its iterations/tool calls so actual spend stays under the wallet
- Ensure every model in the child's graph is catalog-priced to avoid the incomplete-ledger path
- Inspect the child receipt (usage.receipts) to see where the dollars went before resizing
Example fix
// before
const child = parent.subagent({ maxCostUsd: 0.5 }); // child burns 0.62 -> throw
// after
const child = parent.subagent({ maxCostUsd: 1.5 }); Defensive patterns
Strategy: try-catch
Try / catch
try {
return await dispatchSubagent(task);
} catch (error) {
if (error instanceof Error && error.message === 'cave_subagent_cost_budget') {
// wallet exhausted mid-run: surface partial child work if captured, then stop this branch
return reportWalletExhausted(toolName);
}
throw error;
} Prevention
- Size subagent maxCostUsd wallets with 2-3x headroom over the expected catalog-priced cost
- Keep the wallet carve within the parent's remaining budget when raising it
- Ensure every model in the child graph is priced so the incomplete-ledger clause cannot fire
- Inspect child receipts after each run and resize wallets before the next run
When it happens
Trigger: Child's real catalog-priced spend exceeded its maxCostUsd wallet (wallet sized exactly at expected cost with no headroom); a model inside the child's graph absent from the catalog marked the ledger incomplete, tripping the incomplete clause; descendants of the child spending against the same carved wallet.
Common situations: Wallets sized to the point estimate of a task whose cost varies (long research loops); retry-heavy children; unpriced regional models inside a budgeted child; maxCostUsd inherited from parent config without rescaling.
Related errors
- cave_subagent_wallet_unavailable
- caveman agent: subagent maxCostUsd must be positive
- caveman agent: subagent maxTokens must be a positive integer
- cave_subagent_unpriced_budget
- ${ledger.exceededCode}
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/287a63281f2890e4.
Report an issue: GitHub.