{"record":{"id":"275241228879899d","repo":"ruvnet/ruflo","slug":"estimatedusd-must-be-a-non-negative-finite-number","errorCode":null,"errorMessage":"estimatedUsd must be a non-negative finite number","messagePattern":"estimatedUsd must be a non-negative finite number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/business-pods/bbs-budget-tracker.ts","lineNumber":193,"sourceCode":"        `INSERT INTO bbs_budget_rooms (room_id, monthly_cap_usd, billing_month, _lock_bump)\n         VALUES (?, ?, ?, 0)\n         ON CONFLICT(room_id) DO UPDATE SET monthly_cap_usd = excluded.monthly_cap_usd`,\n      )\n      .run(roomId, monthlyCapUsd, billingMonth);\n  }\n\n  /**\n   * Atomically check budget and insert a reservation row in a single\n   * BEGIN IMMEDIATE transaction. See ADR-164.1 §5.2.\n   */\n  reserve(\n    roomId: string,\n    callerId: string,\n    estimatedUsd: number,\n    opts?: { auditEnvelopeId?: string; expiryMs?: number },\n  ): ReserveResult {\n    if (!Number.isFinite(estimatedUsd) || estimatedUsd < 0) {\n      throw new Error('estimatedUsd must be a non-negative finite number');\n    }\n    const auditEnvelopeId = opts?.auditEnvelopeId ?? `audit-${randomUUID()}`;\n    const expiryMs = clampReservationExpiry(opts?.expiryMs ?? this.defaultExpiryMs);\n\n    const nowMs = this.clock();\n    const billingMonth = currentBillingMonth(nowMs);\n    const billingMonthStart = billingMonthStartMs(billingMonth);\n\n    const beginStmt = this.db.prepare('BEGIN IMMEDIATE');\n    const commitStmt = this.db.prepare('COMMIT');\n    const rollbackStmt = this.db.prepare('ROLLBACK');\n\n    beginStmt.run();\n    let transactionOpen = true;\n    try {\n      // Step 1: touch the room header row (the _lock_bump write makes the\n      // lock acquisition visible per §3.2 peer-review note).\n      const bumpRes = this.db","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/business-pods/bbs-budget-tracker.ts#L175-L211","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","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"],"exampleFix":"// before\ntracker.reserve(roomId, callerId, tokens / pricePerToken /* pricePerToken=0 => Infinity */);\n// after\nconst est = Number.isFinite(tokens / pricePerToken) ? Math.max(0, tokens / pricePerToken) : 0;\ntracker.reserve(roomId, callerId, est);","handlingStrategy":"validation","validationCode":"function toReservationUsd(v: unknown): number {\n  const n = typeof v === 'number' ? v : Number(v);\n  if (!Number.isFinite(n) || n < 0) return 0; // or throw your own upstream error\n  return n;\n}\ntracker.reserve(roomId, callerId, toReservationUsd(rawEstimate));","typeGuard":"function isReservationUsd(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v >= 0;\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["budget","validation","numeric","bbs","pod"],"backgroundTag":"invalid-numeric-input","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}