{"record":{"id":"ef5d2d8bcdf92688","repo":"mastra-ai/mastra","slug":"tokencostcontrol-requires-warnatpercent-to-be-a-nu","errorCode":null,"errorMessage":"TokenCostControl requires warnAtPercent to be a number between 0 and 100 (exclusive)","messagePattern":"TokenCostControl requires warnAtPercent to be a number between 0 and 100 \\(exclusive\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/processors/processors/token-cost-control.ts","lineNumber":266,"sourceCode":"  private scope: CostScope;\n  private window: CostWindow;\n  private strategy: 'block' | 'warn';\n  private messageTemplate: string;\n  private warnAtPercent?: number;\n  private includeBreakdown: boolean;\n  private readonly instanceKey = tokenCostControlInstanceCounter++;\n  public onViolation?: (violation: ProcessorViolation) => void | Promise<void>;\n  private observabilityStorage?: ObservabilityStorage;\n  private logger?: IMastraLogger;\n\n  constructor(options: TokenCostControlOptions) {\n    if (typeof options.maxCost === 'number' && (!Number.isFinite(options.maxCost) || options.maxCost <= 0)) {\n      throw new Error('TokenCostControl requires maxCost to be a finite positive number');\n    }\n\n    if (options.warnAtPercent !== undefined) {\n      if (!Number.isFinite(options.warnAtPercent) || options.warnAtPercent <= 0 || options.warnAtPercent >= 100) {\n        throw new Error('TokenCostControl requires warnAtPercent to be a number between 0 and 100 (exclusive)');\n      }\n      this.warnAtPercent = options.warnAtPercent;\n    }\n\n    this.maxCost = options.maxCost;\n    this.scope = options.scope ?? 'resource';\n    this.window = options.window ?? '7d';\n    this.strategy = options.strategy ?? 'block';\n    this.messageTemplate = options.message ?? 'Cost control: estimated cost limit exceeded ({usage}/{limit})';\n    this.includeBreakdown = options.includeBreakdown ?? false;\n  }\n\n  __registerMastra(mastra: Mastra<any, any, any, any, any, any, any, any, any, any>): void {\n    const storage = mastra.getStorage();\n    const obsStorage = storage?.stores?.observability;\n    if (!obsStorage || typeof obsStorage.getMetricAggregate !== 'function') {\n      throw new Error(\n        `TokenCostControl requires observability storage with getMetricAggregate support. ` +","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/processors/processors/token-cost-control.ts#L248-L284","documentation":"TokenCostControl supports an early-warning threshold at a percentage of the budget. `warnAtPercent` is optional, but when provided it must be a finite number strictly between 0 and 100 (both endpoints excluded) — 0 would warn always and 100 would only warn when the cap is already hit, neither of which is meaningful. The constructor throws otherwise.","triggerScenarios":"`new TokenCostControl({ maxCost: 10, warnAtPercent: 0 })`, `warnAtPercent: 100`, `warnAtPercent: -20`, `warnAtPercent: NaN/Infinity`, or a float like `0.05` intended as a fraction (0–1 scale) instead of a percentage (0–100 scale).","commonSituations":"Confusing fraction with percent (0.8 meaning 80%), loading the value from a slider/config that allows edge values, division producing NaN, or forgetting it is exclusive of the bounds.","solutions":["Provide a percentage strictly between 0 and 100, e.g. `warnAtPercent: 80`.","Convert fractions to percent: `warnAtPercent: fraction * 100`.","Clamp/sanitize: `Math.min(99.9, Math.max(0.1, value))`.","Omit the option entirely if no early warning is needed."],"exampleFix":"// before\nnew TokenCostControl({ maxCost: 10, warnAtPercent: 0.8 });\n// after\nnew TokenCostControl({ maxCost: 10, warnAtPercent: 80 });","handlingStrategy":"validation","validationCode":"const v = options.warnAtPercent;\nif (v !== undefined && (!Number.isFinite(v) || v <= 0 || v >= 100)) {\n  throw new TypeError(`warnAtPercent must be between 0 and 100 (exclusive), got ${v}`);\n}","typeGuard":"function isValidWarnPercent(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v > 0 && v < 100;\n}","tryCatchPattern":"try {\n  controller = new TokenCostControl(opts);\n} catch (e) {\n  if (e.message.includes('warnAtPercent')) {\n    controller = new TokenCostControl({ ...opts, warnAtPercent: undefined });\n  } else throw e;\n}","preventionTips":["Remember the option is a percent (0-100), not a fraction (0-1); multiply fractions by 100.","Clamp UI slider/config values into (0, 100) exclusive before passing.","Omit the option when no early warning is needed instead of using 0/100 as 'always'/'never'."],"tags":["configuration","validation","cost-control","constructor"],"backgroundTag":"invalid-parameter-value","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}