JuliusBrussee/caveman · error · Error
cave_budget_output_floor_invalid
Error message
cave_budget_output_floor_invalid
What it means
Thrown by normalizeRunBudget when outputFloorTokens is not a safe integer or is not positive. The output floor is the minimum output-token headroom the runtime reserves on each call; a zero, negative, fractional, or non-numeric floor makes that clamp meaningless, so it is rejected. The field is optional and defaults to OUTPUT_CLAMP_FLOOR_TOKENS, so this only fires when a caller overrides it badly.
Source
Thrown at packages/agent/src/budget.ts:112
const denomination: BudgetDenomination = usd ? "usd" : "tokens";
const max = usd ? budget.maxUsd! : budget.maxTokens!;
if (!Number.isFinite(max) || max <= 0) throw new Error("cave_budget_max_invalid");
if (denomination === "tokens" && !Number.isSafeInteger(max)) {
throw new Error("cave_budget_max_invalid");
}
const wrongInitial = denomination === "usd" ? budget.initialTokens : budget.initialUsd;
if (wrongInitial !== undefined) throw new Error("cave_budget_denomination_ambiguous");
const declaredInitial = denomination === "usd" ? budget.initialUsd : budget.initialTokens;
const initial = declaredInitial ?? max;
if (!Number.isFinite(initial) || initial <= 0 || initial > max) {
throw new Error("cave_budget_initial_invalid");
}
if (denomination === "tokens" && !Number.isSafeInteger(initial)) {
throw new Error("cave_budget_initial_invalid");
}
const outputFloorTokens = budget.outputFloorTokens ?? OUTPUT_CLAMP_FLOOR_TOKENS;
if (!Number.isSafeInteger(outputFloorTokens) || outputFloorTokens <= 0) {
throw new Error("cave_budget_output_floor_invalid");
}
const onExhausted = budget.onExhausted ?? "compact";
if (onExhausted !== "compact" && onExhausted !== "stop") {
throw new Error("cave_budget_on_exhausted_invalid");
}
return Object.freeze({
denomination,
max,
initial,
outputFloorTokens,
onExhausted,
compaction: normalizeCompaction(budget.compaction),
});
}
/** Identity and shape of one prospective provider call. */
export interface CallCeiling {
readonly provider: string;View on GitHub (pinned to 27d5a3981a)
Solutions
- If you need a different floor, pass a positive safe integer (e.g. outputFloorTokens: 2048).
- To use the built-in default, omit the field entirely rather than passing 0.
- Validate env-derived values: Number.isSafeInteger(n) && n > 0 before including them in the budget.
Example fix
// before
const budget = { maxUsd: 5, outputFloorTokens: 0 }; // attempting to disable the floor
// after
const budget = { maxUsd: 5, outputFloorTokens: 2048 }; Defensive patterns
Strategy: validation
Validate before calling
const floor = process.env.OUTPUT_FLOOR !== undefined ? Number(process.env.OUTPUT_FLOOR) : undefined;
const budget = {
maxUsd: 5,
...(floor !== undefined && Number.isSafeInteger(floor) && floor > 0 ? { outputFloorTokens: floor } : {}),
}; Type guard
function isValidOutputFloor(v: unknown): v is number {
return typeof v === "number" && Number.isSafeInteger(v) && v > 0;
} Prevention
- Omit outputFloorTokens to use the built-in default; do not pass 0.
- Validate env-sourced floors with Number.isSafeInteger && > 0.
- Remember the floor clamps output token caps per call; a value larger than your max is also suspicious.
When it happens
Trigger: Passing outputFloorTokens: 0 (attempting to disable the clamp); passing a float like 512.5; passing NaN or a negative number; passing a numeric string such as "1024".
Common situations: Tuning the floor from an env var without validating the parse; copying a fractional default from documentation or a blog post; attempting to disable output clamping entirely by setting the floor to zero.
Related errors
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
- cave_budget_on_exhausted_invalid
- cave_budget_initial_invalid
- cave_budget_release_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/9dc77ceb7c76e5e8.
Report an issue: GitHub.