{"record":{"id":"bdae5138d8ba1d50","repo":"mastra-ai/mastra","slug":"key-exists-but-is-not-a-number","errorCode":null,"errorMessage":"${key} exists but is not a number","messagePattern":"(.+?) exists but is not a number","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/cache/inmemory.ts","lineNumber":105,"sourceCode":"  }\n\n  async delete(key: string): Promise<void> {\n    this.cache.delete(key);\n  }\n\n  async clear(): Promise<void> {\n    this.cache.clear();\n  }\n\n  async increment(key: string): Promise<number> {\n    const value = this.cache.get(key);\n    let counter: number;\n    if (value === undefined) {\n      counter = 1;\n    } else if (typeof value === 'number') {\n      counter = value + 1;\n    } else {\n      throw new Error(`${key} exists but is not a number`);\n    }\n    this.cache.set(key, counter);\n    return counter;\n  }\n}\n","sourceCodeStart":87,"sourceCodeEnd":111,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/cache/inmemory.ts#L87-L111","documentation":"InMemoryCache.increment reads the current value at the key, adds 1, and writes it back. If the stored value exists but is not a number (string, object, array), it throws instead of coercing, preventing silent data corruption of counters.","triggerScenarios":"Calling await cache.increment(key) when the key was previously set via cache.set(key, 'some-string') or listPush(key, ...), so the existing value is not numeric.","commonSituations":"Key collisions between a list/scalar writer and a counter writer, refactored code that changed the value shape stored under a key, or serialized cache data restored with the wrong types.","solutions":["Use a dedicated key namespace for counters (e.g. 'count:...') distinct from list/string keys","Delete the existing non-numeric key before incrementing to reset the counter","Call cache.set(key, 0) first if you need to reset the counter explicitly"],"exampleFix":"// before\nawait cache.set('visits', 'many');\nawait cache.increment('visits'); // throws\n// after\nawait cache.set('visits', 0);\nawait cache.increment('visits'); // 1","handlingStrategy":"validation","validationCode":"const current = await cache.get(key);\nif (current !== undefined && typeof current !== 'number') {\n  throw new TypeError(`Key ${key} is not a numeric counter; reset it before incrementing`);\n}\nawait cache.increment(key);","typeGuard":"function isNumberCacheValue(v: unknown): v is number {\n  return typeof v === 'number';\n}","tryCatchPattern":"try {\n  await cache.increment(key);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('is not a number')) {\n    await cache.set(key, 0);\n    await cache.increment(key);\n  } else throw err;\n}","preventionTips":["Reserve distinct key prefixes for counters","Only store numbers under counter keys","Reset with set(key, 0) when re-purposing a key"],"tags":["cache","type-conflict","counter"],"backgroundTag":"cache-type-conflict","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}