Automattic/mongoose · error · Error

Mongoose maps do not support keys that start with "$", got "

Error message

Mongoose maps do not support keys that start with "$", got "${key}"

What it means

checkValidKey() rejects Map keys starting with '$'. MongoDB reserves $-prefixed field names for operators, so storing such a key inside the object-backed Map would produce unqueryable or rejected documents.

Source

Thrown at lib/types/map.js:358

  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. Prefix or escape the key: doc.settings.set('x' + key, value) or replace '$' with '_'
  2. Sanitize external keys before they reach the Map: key = key.replace(/^\$+/, '_')
  3. Reject $-prefixed keys at the API boundary with a 400 response

Example fix

// before
doc.meta.set('$amount', 5);
// after
doc.meta.set('amount', 5); // or sanitize: key.replace(/^\$/, '_$')
Defensive patterns

Strategy: validation

Validate before calling

function sanitizeMapKey(key) {
  const k = String(key);
  if (k.startsWith('$')) return '_' + k;
  return k;
}
doc.settings.set(sanitizeMapKey(userKey), value);

Type guard

function isSafeMapKey(key) { const k = String(key); return !k.startsWith('$'); }

Try / catch

try { doc.settings.set(k, v); } catch (err) { if (/start with "\$"/.test(err.message)) doc.settings.set('_' + k, v); else throw err; }

Prevention

When it happens

Trigger: doc.settings.set('$limit', 5); user-controlled input like usernames or tags that begin with '$' used directly as Map keys.

Common situations: Storing user-generated identifiers (payment metadata, feature flags) in a Map without sanitization; migrating Redis-style keys that use $ prefixes.

Related errors


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