JuliusBrussee/caveman · error
${ledger.exceededCode}
Error message
${ledger.exceededCode} What it means
Pre-flight reservation for the next model call: for each active ledger, actualUsd + reservedUsd + ceilingUsd must fit under limitUsd, where ceilingUsd is the conservative worst-case cost of the call (byte-derived input ceiling times the catalog's worst rate plus the output allowance - deliberately ~3-4x the likely real cost). When the projection exceeds the limit, the ledger's exceededCode is thrown: 'cave_subagent_cost_budget' for subagent wallets (set at runtime.ts:3977) or 'cave_run_cost_budget_exceeded' for the root maxCostUsd ledger (runtime.ts:794). This is the older error-terminating cap; RunOptions.budget instead stops cleanly between calls with stopReason.
Source
Thrown at packages/agent/src/runtime.ts:4671
): SpendReservation[] {
if (ledgers.length === 0) return [];
const outputTokens = Math.min(
model.maxTokens,
requestedOutputTokens ?? model.maxTokens,
);
const ceilingUsd = catalogSearchCeiling(
`${model.provider}/${model.id}`,
model.contextWindow,
outputTokens,
);
if (ceilingUsd === undefined) {
markSpendIncomplete(ledgers);
throw new Error("cave_subagent_unpriced_budget");
}
for (const ledger of ledgers) {
if (ledger.incomplete) throw new Error("cave_subagent_spend_evidence_incomplete");
if (ledger.actualUsd + ledger.reservedUsd + ceilingUsd > ledger.limitUsd) {
throw new Error(ledger.exceededCode);
}
}
const reservations = ledgers.map((ledger) => ({
ledger,
ceilingUsd,
provider: model.provider,
model: model.id,
}));
for (const { ledger } of reservations) ledger.reservedUsd += ceilingUsd;
return reservations;
}
function settleProviderSpend(
reservations: readonly SpendReservation[],
usage: ValidatedProviderUsage,
): Error | undefined {
if (reservations.length === 0) return undefined;
const requested = reservations[0]!;View on GitHub (pinned to 766dce6b13)
Solutions
- Raise the limit (maxCostUsd / subagent cap) so the worst-case ceiling fits with headroom
- Lower requestedOutputTokens for the call so the ceiling shrinks
- Prefer RunOptions.budget (reserve-and-clamp): it clamps output to what remains and stops between calls with stopReason instead of throwing
- Reduce the number of parallel budgeted subagents sharing one cap
Example fix
// before: error-terminating cap sized too tight for worst-case
await run(agent, { maxCostUsd: 1, requestedOutputTokens: 32_000 });
// after: clamping budget, or bigger cap for worst case
await run(agent, { budget: { denomination: 'usd', maxUsd: 1 } }); // clamps + stopReason: budget_exhausted Defensive patterns
Strategy: try-catch
Try / catch
try {
return await run(agent, opts);
} catch (error) {
const msg = error instanceof Error ? error.message : '';
if (msg === 'cave_subagent_cost_budget' || msg === 'cave_run_cost_budget_exceeded') {
// worst-case reservation no longer fits: raise the cap or lower output tokens
return await run(agent, { ...opts, maxCostUsd: opts.maxCostUsd! * 2 });
}
throw error;
} Prevention
- Size maxCostUsd for the worst-case reservation (byte-derived ceiling ~3-4x real token cost), not the average
- Prefer RunOptions.budget (reserve-and-clamp, stops with stopReason) over the error-throwing maxCostUsd cap
- Keep requestedOutputTokens modest so per-call ceilings fit the remaining cap
- Limit how many budgeted subagents share one root cap per turn
When it happens
Trigger: The worst-case ceiling of the next call no longer fits the remaining wallet/root cap; large requestedOutputTokens inflating the ceiling past the limit; several subagents sharing one root maxCostUsd so reservations stack; late-run calls after most of the cap is already actual+reserved spend.
Common situations: maxCostUsd sized to expected average cost rather than worst-case reservation; raising requested output tokens mid-run; fan-out of budgeted subagents against a small root cap; conservative ceiling on huge contexts (byte bound ~3-4x tokens) tripping early.
Related errors
- cave_subagent_cost_budget
- cave_subagent_unpriced_budget
- cave_breaker_retry_requires_budget
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/1b62ddb46791b89b.
Report an issue: GitHub.