{"record":{"id":"758e2723f8398b2c","repo":"Automattic/mongoose","slug":"mongoose-maps-do-not-support-keys-that-contain","errorCode":null,"errorMessage":"Mongoose maps do not support keys that contain \".\", got \"${key}\"","messagePattern":"Mongoose maps do not support keys that contain \"\\.\", got \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/types/map.js","lineNumber":361,"sourceCode":"});\n\n/**\n * Since maps are stored as objects under the hood, keys must be strings\n * and can't contain any invalid characters\n * @param {string} key\n * @api private\n */\n\nfunction checkValidKey(key) {\n  const keyType = typeof key;\n  if (keyType !== 'string') {\n    throw new TypeError(`Mongoose maps only support string keys, got ${keyType}`);\n  }\n  if (key.startsWith('$')) {\n    throw new Error(`Mongoose maps do not support keys that start with \"$\", got \"${key}\"`);\n  }\n  if (key.includes('.')) {\n    throw new Error(`Mongoose maps do not support keys that contain \".\", got \"${key}\"`);\n  }\n  if (specialProperties.has(key)) {\n    throw new Error(`Mongoose maps do not support reserved key name \"${key}\"`);\n  }\n}\n\nmodule.exports = MongooseMap;\n","sourceCodeStart":343,"sourceCodeEnd":369,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/types/map.js#L343-L369","documentation":"checkValidKey() rejects Map keys containing '.', because Mongoose and MongoDB use dots as path separators. A dotted key would be ambiguous with nested paths in updates and queries, so it is refused.","triggerScenarios":"doc.emails.set('user@example.com', data) — email contains a dot; keys derived from file paths, domain names, version strings ('1.2.3'), or dotted identifiers from user input.","commonSituations":"Using emails, hostnames, file paths, or semantic-version strings as Map keys; porting objects that allowed dots to a Mongoose Map.","solutions":["Replace dots with a safe delimiter: key.split('.').join(':') or key.replaceAll('.', '_')","Use URL-encoding for arbitrary keys: encodeURIComponent(key)","Model dotted identifiers as separate fields or an array of subdocuments instead of a Map"],"exampleFix":"// before\ndoc.logins.set('user@example.com', new Date());\n// after\ndoc.logins.set('user@example~com', new Date()); // dot replaced","handlingStrategy":"validation","validationCode":"function encodeMapKey(key) {\n  const k = String(key);\n  if (k.includes('.')) return k.split('.').join('\\u2024'); // or '_'\n  return k;\n}\ndoc.index.set(encodeMapKey('user@example.com'), v);","typeGuard":"function isDotFreeKey(key) { return !String(key).includes('.'); }","tryCatchPattern":"try { doc.index.set(k, v); } catch (err) { if (/contain \"\\.\"/.test(err.message)) doc.index.set(k.replaceAll('.', '_'), v); else throw err; }","preventionTips":["Never use emails, hostnames, or file paths raw as Map keys","Encode arbitrary keys (encodeURIComponent or dot-replacement) at the ingestion boundary","Consider an array of { key, value } subdocuments for naturally dotted identifiers"],"tags":["mongoose","map","keys","dotted-path"],"backgroundTag":"invalid-map-key","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}