{"record":{"id":"ef947fa4728867f1","repo":"ruvnet/ruflo","slug":"actualusd-must-be-a-non-negative-finite-number","errorCode":null,"errorMessage":"actualUsd must be a non-negative finite number","messagePattern":"actualUsd must be a non-negative finite number","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/business-pods/bbs-budget-tracker.ts","lineNumber":299,"sourceCode":"      return { ok: true, reservationId, remainingAfterReserve: remaining };\n    } catch (err) {\n      if (transactionOpen) {\n        try { rollbackStmt.run(); } catch { /* already-rolled */ }\n      }\n      throw err;\n    }\n  }\n\n  /**\n   * Commit the reservation with the actual cost. Late commits (expired\n   * before commit landed) ARE accepted, transitioned to\n   * 'committed_post_expiry', charged to the budget, and surfaced via\n   * `warned: 'COMMIT_AFTER_EXPIRY'` plus a `reservation.committed_post_expiry`\n   * audit emit. See ADR-164.1 §5.3 + §8.1.\n   */\n  commit(reservationId: string, actualUsd: number): CommitResult {\n    if (!Number.isFinite(actualUsd) || actualUsd < 0) {\n      throw new Error('actualUsd must be a non-negative finite number');\n    }\n    const nowMs = this.clock();\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      const row = this.db\n        .prepare(\n          `SELECT state, room_id, estimated_usd, reserved_at, expires_at\n             FROM bbs_budget_reservations\n             WHERE reservation_id = ?`,\n        )\n        .get(reservationId) as\n        | { state: string; room_id: string; estimated_usd: number; reserved_at: number; expires_at: number }","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/business-pods/bbs-budget-tracker.ts#L281-L317","documentation":"Input guard at the top of AtomicBbsRoomBudgetTracker.commit(), symmetric to the reserve() guard (error 163). Validates actualUsd — the real cost charged against a previously reserved amount — before opening the BEGIN IMMEDIATE transaction. Uses Number.isFinite() and a < 0 test. Rejecting here prevents a malformed actual cost from corrupting committed totals or violating the SQL CHECK on actual_usd.","triggerScenarios":"Calling tracker.commit(reservationId, actualUsd) where actualUsd is NaN, ±Infinity, or negative. This runs after a reservation was already created by reserve() and the actual spend is being finalized.","commonSituations":"Actual cost reported by an external billing API as null/undefined then coerced to NaN; a usage meter returning -1 on error; a division that yields Infinity; a cost-aggregation sum that includes a NaN term poisoning the total.","solutions":["Validate before calling: `if (!Number.isFinite(actualUsd) || actualUsd < 0) throw ...` or clamp to the reserved estimate","If actual cost is unknown at commit time, commit the reserved estimatedUsd as the actual (the API accepts over/under-runs against the reservation)","Filter NaN out of any summation feeding actualUsd before it reaches commit()"],"exampleFix":"// before:\nconst actual = sumUsage(usageRows); // NaN if any row has null cost\ntracker.commit(reservationId, actual); // throws\n\n// after:\nconst actual = usageRows.reduce((a, r) => a + (Number.isFinite(r.cost) ? r.cost : 0), 0);\ntracker.commit(reservationId, Math.max(0, actual));","handlingStrategy":"validation","validationCode":"function safeActualCost(actualUsd: unknown): number {\n  const n = typeof actualUsd === 'number' ? actualUsd : Number(actualUsd);\n  if (!Number.isFinite(n) || n < 0) return 0;\n  return n;\n}\n// before calling commit():\nconst actual = safeActualCost(reportedCost);\ntracker.commit(reservationId, actual);","typeGuard":"function isValidActualCost(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v >= 0;\n}","tryCatchPattern":null,"preventionTips":["Filter NaN out of any summation that feeds actualUsd before calling commit()","If actual cost is unavailable at commit time, commit the reserved estimatedUsd as a safe fallback","Guard external billing-API responses against null/undefined before coercion"],"tags":["budget","validation","input","bbs","numbers"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}