mastra-ai/mastra · error

${key} exists but is not a number

Error message

${key} exists but is not a number

What it means

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.

Source

Thrown at packages/core/src/cache/inmemory.ts:105

  }

  async delete(key: string): Promise<void> {
    this.cache.delete(key);
  }

  async clear(): Promise<void> {
    this.cache.clear();
  }

  async increment(key: string): Promise<number> {
    const value = this.cache.get(key);
    let counter: number;
    if (value === undefined) {
      counter = 1;
    } else if (typeof value === 'number') {
      counter = value + 1;
    } else {
      throw new Error(`${key} exists but is not a number`);
    }
    this.cache.set(key, counter);
    return counter;
  }
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Use a dedicated key namespace for counters (e.g. 'count:...') distinct from list/string keys
  2. Delete the existing non-numeric key before incrementing to reset the counter
  3. Call cache.set(key, 0) first if you need to reset the counter explicitly

Example fix

// before
await cache.set('visits', 'many');
await cache.increment('visits'); // throws
// after
await cache.set('visits', 0);
await cache.increment('visits'); // 1
Defensive patterns

Strategy: validation

Validate before calling

const current = await cache.get(key);
if (current !== undefined && typeof current !== 'number') {
  throw new TypeError(`Key ${key} is not a numeric counter; reset it before incrementing`);
}
await cache.increment(key);

Type guard

function isNumberCacheValue(v: unknown): v is number {
  return typeof v === 'number';
}

Try / catch

try {
  await cache.increment(key);
} catch (err) {
  if (err instanceof Error && err.message.includes('is not a number')) {
    await cache.set(key, 0);
    await cache.increment(key);
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/bdae5138d8ba1d50. Report an issue: GitHub.