{"record":{"id":"85ca2ae7c4951331","repo":"mastra-ai/mastra","slug":"modelbyinputtokens-threshold-keys-must-be-positive","errorCode":null,"errorMessage":"ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}","messagePattern":"ModelByInputTokens threshold keys must be positive numbers\\. Got: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/model-by-input-tokens.ts","lineNumber":38,"sourceCode":"    'modelId' in model ||\n    'id' in model ||\n    'providerId' in model ||\n    'provider' in model ||\n    ('doGenerate' in model && 'doStream' in model)\n  );\n}\n\nfunction normalizeThresholds(config: ModelByInputTokensConfig) {\n  const entries = Object.entries(config.upTo);\n\n  if (entries.length === 0) {\n    throw new Error('ModelByInputTokens requires at least one threshold in \"upTo\"');\n  }\n\n  for (const [limitStr, model] of entries) {\n    const limit = Number(limitStr);\n    if (!Number.isFinite(limit) || limit <= 0) {\n      throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);\n    }\n\n    if (!isTieredModelTarget(model)) {\n      throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);\n    }\n  }\n\n  return entries.map(([limitStr, model]) => ({ limit: Number(limitStr), model })).sort((a, b) => a.limit - b.limit);\n}\n\nexport class ModelByInputTokens {\n  private readonly thresholds: Array<{ limit: number; model: AgentConfig['model'] }>;\n\n  constructor(config: ModelByInputTokensConfig) {\n    this.thresholds = normalizeThresholds(config);\n  }\n\n  resolve(inputTokens: number): AgentConfig['model'] {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/model-by-input-tokens.ts#L20-L56","documentation":"normalizeThresholds converts the string keys of the upTo map into numeric token limits. Every key must parse to a finite number greater than zero; otherwise the processor would have unusable thresholds (NaN, 0, negative limits) and cannot order or compare them against input token counts.","triggerScenarios":"`new ModelByInputTokens({ upTo: { '0': model } })`, `{ '-5000': model }`, `{ 'abc': model }`, or keys like `{ '': model }` / `{ '12e999': model }` that yield NaN or non-finite values when passed through Number().","commonSituations":"Typo in a threshold key (e.g. '1,28000' with a comma, or '12k' with a unit suffix); template-literal keys built from undefined variables producing 'undefined' or 'NaN'; locale-formatted numbers with dots/commas; copying config where a key was left as a placeholder.","solutions":["Change the offending key to a plain positive numeric string, e.g. { '128000': model }","Remove unit suffixes and thousand separators from keys ('12k' -> '12000', '128,000' -> '128000')","Log/inspect the upTo keys and convert them with Number() yourself to find which one is invalid"],"exampleFix":"// before\nnew ModelByInputTokens({ upTo: { '12k': 'openai/gpt-4o-mini', '128000': 'openai/gpt-4o' } });\n// after\nnew ModelByInputTokens({ upTo: { '12000': 'openai/gpt-4o-mini', '128000': 'openai/gpt-4o' } });","handlingStrategy":"validation","validationCode":"for (const key of Object.keys(upTo)) {\n  const n = Number(key);\n  if (!Number.isFinite(n) || n <= 0) throw new Error(`Invalid upTo key: \"${key}\"`);\n}","typeGuard":"function hasValidThresholdKeys(upTo: Record<string, unknown>): boolean {\n  return Object.keys(upTo).every(k => { const n = Number(k); return Number.isFinite(n) && n > 0; });\n}","tryCatchPattern":"try {\n  processor = new ModelByInputTokens({ upTo });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('positive numbers')) {\n    const fixed = Object.fromEntries(Object.entries(upTo).map(([k, v]) => [String(Math.max(1, Number(k) || 1)), v]));\n    processor = new ModelByInputTokens({ upTo: fixed });\n  } else throw e;\n}","preventionTips":["Use plain numeric string keys without units or separators","Coerce dynamic keys with Number() and validate before building the map","Avoid template-literal keys built from possibly-undefined variables"],"tags":["config","validation","observational-memory"],"backgroundTag":"invalid-config-value","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}