{"record":{"id":"9e37e8813b4e3c98","repo":"ruvnet/ruflo","slug":"budgetusdperrun-must-not-exceed-budgetusdmonthly","errorCode":null,"errorMessage":"budgetUsdPerRun must not exceed budgetUsdMonthly","messagePattern":"budgetUsdPerRun must not exceed budgetUsdMonthly","errorType":"validation","errorClass":"PodTemplateValidationError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/business-pods/pod-schema.ts","lineNumber":244,"sourceCode":"  }\n  const budgetUsdMonthly = requireNumber(json, 'budgetUsdMonthly', '/');\n  if (budgetUsdMonthly < 0) {\n    throw new PodTemplateValidationError('budgetUsdMonthly must be ≥0', '/');\n  }\n  const budgetUsdPerRun = requireNumber(json, 'budgetUsdPerRun', '/');\n  if (budgetUsdPerRun < 0) {\n    throw new PodTemplateValidationError('budgetUsdPerRun must be ≥0', '/');\n  }\n  if (budgetUsdMonthly > 0 && budgetUsdPerRun > budgetUsdMonthly) {\n    throw new PodTemplateValidationError(\n      'budgetUsdPerRun must not exceed budgetUsdMonthly',\n      '/',\n    );\n  }\n  const preferLocalExecution = requireBoolean(json, 'preferLocalExecution', '/');\n  const cronSchedule = requireString(json, 'cronSchedule', '/');\n  if (!CRON_RE.test(cronSchedule)) {\n    throw new PodTemplateValidationError(\n      'cronSchedule must be a POSIX cron expression (5 or 6 fields)',\n      '/',\n    );\n  }\n  const auditReadView = validateAuditReadView(json.auditReadView, '/auditReadView');\n\n  let reservationExpiryMs: number | undefined;\n  if (json.reservationExpiryMs !== undefined) {\n    const v = requireNumber(json, 'reservationExpiryMs', '/');\n    // ADR-164.1 §3.2 — bounded to [5_000, 300_000] ms.\n    if (v < 5_000 || v > 300_000) {\n      throw new PodTemplateValidationError(\n        'reservationExpiryMs must be within [5000, 300000] ms (ADR-164.1 §3.2)',\n        '/',\n      );\n    }\n    reservationExpiryMs = v;\n  }","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/business-pods/pod-schema.ts#L226-L262","documentation":"This is the raw constructor argument for the same budgetUsdPerRun > budgetUsdMonthly check. The string 'budgetUsdPerRun must not exceed budgetUsdMonthly' is the first argument to 'new PodTemplateValidationError(message, path)' before the constructor prepends 'pod-template at ${path}: '. A developer inspecting the throw site or the raw message field sees this form; the constructed Error.message includes the prefix.","triggerScenarios":"budgetUsdMonthly > 0 && budgetUsdPerRun > budgetUsdMonthly. Same logical condition as the constructed error — the raw message is what the throw statement passes to the PodTemplateValidationError constructor.","commonSituations":"Same as the constructed form: per-run budget exceeds monthly cap when a monthly cap is active (>0). Encountered when inspecting source or matching against the raw message string in error-handling code that reads the constructor argument rather than .message.","solutions":["Ensure budgetUsdPerRun <= budgetUsdMonthly when budgetUsdMonthly > 0","Set budgetUsdMonthly to 0 to disable the monthly cap entirely","Match on 'PodTemplateValidationError' name rather than the raw message string in catch blocks"],"exampleFix":"// before\n{ \"budgetUsdMonthly\": 100, \"budgetUsdPerRun\": 150 }\n\n// after\n{ \"budgetUsdMonthly\": 0, \"budgetUsdPerRun\": 150 }","handlingStrategy":"validation","validationCode":"const monthly = template.budgetUsdMonthly;\nconst perRun = template.budgetUsdPerRun;\nif (monthly > 0 && perRun > monthly) {\n  throw new Error('budgetUsdPerRun must not exceed budgetUsdMonthly');\n}","typeGuard":"function budgetsAreConsistent(monthly: number, perRun: number): boolean {\n  return monthly === 0 || perRun <= monthly;\n}","tryCatchPattern":"try {\n  validatePodTemplate(json);\n} catch (e) {\n  if (e instanceof PodTemplateValidationError) {\n    // e.message includes 'pod-template at /: budgetUsdPerRun must not exceed budgetUsdMonthly'\n    // Match on e.name === 'PodTemplateValidationError' rather than raw message\n  }\n}","preventionTips":["Match on PodTemplateValidationError.name rather than the raw constructor message string","Ensure per-run budget does not exceed monthly budget when monthly > 0","Use 0 for budgetUsdMonthly to skip this check entirely"],"tags":["pod-template","validation","schema","budget"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}