ruvnet/ruflo · error
estimatedUsd must be a non-negative finite number
Error message
estimatedUsd must be a non-negative finite number
What it means
BBS budget tracker reserve() rejects its estimatedUsd argument before opening the BEGIN IMMEDIATE transaction unless it is a finite, non-negative number. This guards the atomic budget-check-and-reserve path (ADR-164.1 §5.2) from NaN/Infinity/negative estimates that would corrupt ledger arithmetic.
Solutions
- Pass a finite non-negative number: clamp or default the estimate, e.g. Number.isFinite(est) && est >= 0 ? est : 0
- Fix upstream NaN sources: guard divisions and parseFloat results before they reach reserve()
- If cost is genuinely unknown, reserve 0 and commit the actual cost later via commit()
- Coerce string amounts with Number(...) and validate before calling
Example fix
// before tracker.reserve(roomId, callerId, tokens / pricePerToken /* pricePerToken=0 => Infinity */); // after const est = Number.isFinite(tokens / pricePerToken) ? Math.max(0, tokens / pricePerToken) : 0; tracker.reserve(roomId, callerId, est);
Defensive patterns
Strategy: validation
Validate before calling
function toReservationUsd(v: unknown): number {
const n = typeof v === 'number' ? v : Number(v);
if (!Number.isFinite(n) || n < 0) return 0; // or throw your own upstream error
return n;
}
tracker.reserve(roomId, callerId, toReservationUsd(rawEstimate)); Type guard
function isReservationUsd(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0;
} Prevention
- Validate cost-model outputs (NaN from missing prices, Infinity from /0) at the source
- Reserve 0 for unknown costs and charge actuals via commit()
- Unit-test the boundary with NaN, Infinity, -1, and '4.20' inputs
When it happens
Trigger: Calling tracker.reserve(roomId, callerId, estimatedUsd) where estimatedUsd is NaN (0/0, parseFloat('n/a')), Infinity (division by zero cost estimate), a negative number (credit math applied too early), or a numeric string ('4.20') since TypeScript types don't exist at runtime.
Common situations: Cost model returning NaN when a provider price list entry is missing; dividing by a zero token count; JSON config carrying a string amount; unit tests passing -1 as a sentinel for 'unknown cost'.
Related errors
- actualUsd must be a non-negative finite number
- agent must be an object
- bench must be an object
- bench.successCriteria must have ≥1 entry
- field " " must be a boolean
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/275241228879899d.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/business-pods/bbs-budget-tracker.ts:193
`INSERT INTO bbs_budget_rooms (room_id, monthly_cap_usd, billing_month, _lock_bump)
VALUES (?, ?, ?, 0)
ON CONFLICT(room_id) DO UPDATE SET monthly_cap_usd = excluded.monthly_cap_usd`,
)
.run(roomId, monthlyCapUsd, billingMonth);
}
/**
* Atomically check budget and insert a reservation row in a single
* BEGIN IMMEDIATE transaction. See ADR-164.1 §5.2.
*/
reserve(
roomId: string,
callerId: string,
estimatedUsd: number,
opts?: { auditEnvelopeId?: string; expiryMs?: number },
): ReserveResult {
if (!Number.isFinite(estimatedUsd) || estimatedUsd < 0) {
throw new Error('estimatedUsd must be a non-negative finite number');
}
const auditEnvelopeId = opts?.auditEnvelopeId ?? `audit-${randomUUID()}`;
const expiryMs = clampReservationExpiry(opts?.expiryMs ?? this.defaultExpiryMs);
const nowMs = this.clock();
const billingMonth = currentBillingMonth(nowMs);
const billingMonthStart = billingMonthStartMs(billingMonth);
const beginStmt = this.db.prepare('BEGIN IMMEDIATE');
const commitStmt = this.db.prepare('COMMIT');
const rollbackStmt = this.db.prepare('ROLLBACK');
beginStmt.run();
let transactionOpen = true;
try {
// Step 1: touch the room header row (the _lock_bump write makes the
// lock acquisition visible per §3.2 peer-review note).
const bumpRes = this.dbView on GitHub (pinned to fa13ee4ad6)