{"record":{"id":"02b357b672521ee8","repo":"Automattic/mongoose","slug":"field-path-is-not-in-schema-and-strict-mode-i-02b357","errorCode":null,"errorMessage":"Field `${path}` is not in schema and strict mode is set to throw.","messagePattern":"Field `(.+?)` is not in schema and strict mode is set to throw\\.","errorType":"exception","errorClass":"StrictModeError","httpStatus":null,"severity":"error","filePath":"lib/document.js","lineNumber":1349,"sourceCode":"        // allow changes to sub paths of mixed types\n        mixed = true;\n        break;\n      } else if (schema.$isSchemaMap && schema.$__schemaType instanceof MixedSchema && i < parts.length - 1) {\n        // Map of mixed and not the last element in the path resolves to mixed\n        mixed = true;\n        schema = schema.$__schemaType;\n        break;\n      }\n    }\n\n    if (schema == null) {\n      // Check for embedded discriminators\n      schema = getEmbeddedDiscriminatorPath(this, path);\n    }\n\n    if (!mixed && !schema) {\n      if (strict === 'throw') {\n        throw new StrictModeError(path);\n      }\n      return this;\n    }\n  } else if (pathType === 'virtual') {\n    schema = this.$__schema.virtualpath(path);\n    schema.applySetters(val, this);\n    return this;\n  } else {\n    schema = this.$__path(path);\n  }\n\n  // gh-4578, if setting a deeply nested path that doesn't exist yet, create it\n  let cur = this._doc;\n  let curPath = '';\n  for (i = 0; i < parts.length - 1; ++i) {\n    cur = cur instanceof Map ? cur.get(parts[i]) : cur[parts[i]];\n    curPath += (curPath.length !== 0 ? '.' : '') + parts[i];\n    if (!cur) {","sourceCodeStart":1331,"sourceCodeEnd":1367,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/document.js#L1331-L1367","documentation":"StrictModeError from the single-path branch of $set ($__set): the path you assigned does not resolve to any schema type - including dotted paths where some segment is missing - and the effective strict mode is 'throw'. Same write-time strict policy as the multi-key variant, reached via `doc.set('a.b', v)` style single-path calls after schema lookup and embedded-discriminator lookup both fail.","triggerScenarios":"`doc.set('nested.unknown', v)` or `doc.set('typoPath', v)` under `strict: 'throw'` when `$__schema.path(path)` returns null; building paths dynamically from user input (e.g. PATCH endpoints mapping JSON paths straight to set()) so arbitrary segments reach the document.","commonSituations":"Dotted-path typos; nested paths whose parent was renamed in a refactor; generic REST wrappers that trust client-supplied path strings.","solutions":["Fix the path so every segment exists in the schema","Add the missing nested path to the schema","Validate dynamic paths against `model.schema.path(p)` before calling set()","Use `strict: true` to drop unknown paths silently instead of throwing"],"exampleFix":"// before\ndoc.set('address.stret', 'x'); // strict: 'throw' -> StrictModeError (typo)\n\n// after\ndoc.set('address.street', 'x');\n// for dynamic paths, validate first:\nif (doc.constructor.schema.path(userPath) != null) doc.set(userPath, value);","handlingStrategy":"validation","validationCode":"// Validate dynamic dotted paths before single-path set()\nconst schemaType = doc.constructor.schema.path(userPath);\nif (schemaType == null && doc.constructor.schema.pathType(userPath) !== 'virtual') {\n  throw new Error(`Refusing to set unknown path ${userPath}`);\n}\ndoc.set(userPath, value);","typeGuard":"const isSettablePath = (doc, p) =>\n  doc.constructor.schema.path(p) != null || doc.constructor.schema.pathType(p) === 'virtual';","tryCatchPattern":"try {\n  doc.set(userPath, value);\n} catch (err) {\n  if (err instanceof mongoose.Error.StrictModeError) {\n    // userPath does not resolve in the schema; reject the request field\n  } else { throw err; }\n}","preventionTips":["Never map client-supplied JSON paths directly to doc.set()","Maintain an allowlist of settable paths in PATCH endpoints","Log the failing path from StrictModeError messages to catch typos quickly"],"tags":["mongoose","strict-mode","schema","set","dotted-path"],"backgroundTag":"strict-mode-unknown-field","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}