Automattic/mongoose · error · TypeError

Mongoose maps only support string keys, got ${keyType}

Error message

Mongoose maps only support string keys, got ${keyType}

What it means

checkValidKey() guards every key written to a MongooseMap. Because Maps are persisted as plain MongoDB objects, keys must be strings; setting a numeric, boolean, symbol, or object key throws a TypeError.

Source

Thrown at lib/types/map.js:355

Object.defineProperty(MongooseMap.prototype, '$__deferredCalls', {
  enumerable: false,
  writable: false,
  configurable: false,
  value: true
});

/**
 * Since maps are stored as objects under the hood, keys must be strings
 * and can't contain any invalid characters
 * @param {string} key
 * @api private
 */

function checkValidKey(key) {
  const keyType = typeof key;
  if (keyType !== 'string') {
    throw new TypeError(`Mongoose maps only support string keys, got ${keyType}`);
  }
  if (key.startsWith('$')) {
    throw new Error(`Mongoose maps do not support keys that start with "$", got "${key}"`);
  }
  if (key.includes('.')) {
    throw new Error(`Mongoose maps do not support keys that contain ".", got "${key}"`);
  }
  if (specialProperties.has(key)) {
    throw new Error(`Mongoose maps do not support reserved key name "${key}"`);
  }
}

module.exports = MongooseMap;

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Convert keys to strings when setting: doc.map.set(String(key), value)
  2. Declare the Map with string-friendly keys at the boundary: { type: Map, of: String } and normalize input before assignment
  3. For ObjectId keys, use the hex string: doc.map.set(id.toHexString(), v)

Example fix

// before
doc.clicks.set(42, 'x'); // TypeError
// after
doc.clicks.set(String(42), 'x');
Defensive patterns

Strategy: type-guard

Validate before calling

function safeMapSet(map, key, value) {
  if (typeof key !== 'string') key = String(key);
  map.set(key, value);
}

Type guard

function isStringKey(key) { return typeof key === 'string'; }

Try / catch

try { doc.map.set(key, val); } catch (err) { if (/only support string keys/.test(err.message)) doc.map.set(String(key), val); else throw err; }

Prevention

When it happens

Trigger: doc.map.set(123, 'x'); doc.map.set(user.id, ...) where user.id is a number or ObjectId; constructing the Map from Object.entries of typed input; using m.set(Symbol('k'), v).

Common situations: Numeric IDs from external systems used as Map keys; values coming from typed APIs, query strings, or BSON types that are not strings.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/3ee09f83900816be. Report an issue: GitHub.