{"record":{"id":"2ae3ee136cb80e64","repo":"Automattic/mongoose","slug":"field-pathtocheck-is-not-in-schema-and-strict","errorCode":null,"errorMessage":"Field `${pathToCheck}` 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/helpers/query/castUpdate.js","lineNumber":391,"sourceCode":"        }\n\n        if (obj[key] === void 0) {\n          delete obj[key];\n          continue;\n        }\n\n        hasKeys = true;\n      } else {\n        const pathToCheck = (prefix + key);\n        const v = schema._getPathType(pathToCheck);\n        let _strict = strict;\n        if (v?.schema && _strict == null) {\n          _strict = v.schema.options.strict;\n        }\n\n        if (v.pathType === 'undefined') {\n          if (_strict === 'throw') {\n            throw new StrictModeError(pathToCheck);\n          } else if (_strict) {\n            delete obj[key];\n            continue;\n          }\n        }\n\n        // gh-2314\n        // we should be able to set a schema-less field\n        // to an empty object literal\n        hasKeys |= walkUpdatePath(schema, val, op, options, context, filter, prefix + key) ||\n          (utils.isObject(val) && utils.hasOwnKeys(val) === false);\n      }\n    } else {\n      const isModifier = !isTopLevelNestedDollarPath && schematype == null &&\n        (key === '$each' || key === '$or' || key === '$and' || key === '$in');\n      const checkPath = isModifier ? prefix : fullPath;\n      if (isModifier) {\n        schematype = schema._getSchema(checkPath);","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/helpers/query/castUpdate.js#L373-L409","documentation":"While walking a nested plain-object value in an update, if the current dotted path resolves to pathType 'undefined' (not in the schema) and effective strict mode is 'throw', walkUpdatePath throws StrictModeError(pathToCheck). Effective strict comes from the query's strict option or the (sub)schema's own strict option, so a subdocument schema with strict: 'throw' can raise this even when the root schema does not.","triggerScenarios":"Schema with strict: 'throw' (or strict: 'throw' on a subdocument) and Model.updateOne(f, { $set: { prefs: { theme: 'dark' } } }) where 'prefs' is not declared; also { $set: { 'prefs.theme': 'dark' } } recursing into an unknown 'prefs' prefix.","commonSituations":"Adding new fields to documents via update without updating the Mongoose schema first; per-subschema strict: 'throw' settings firing on paths the developer believed were covered by the root schema's lenient mode; strict defaulting differences after upgrading to schemas that set strict: 'throw'.","solutions":["Declare the path in the schema; use Schema.Types.Mixed (or a subdocument) for free-form data","Fix typos in the nested path ('pref' vs 'prefs')","Opt out deliberately per query: Model.updateOne(f, update, { strict: false }) — not recommended as a blanket fix"],"exampleFix":"// before: no 'prefs' path, schema strict: 'throw'\nUser.updateOne({ _id }, { $set: { prefs: { theme: 'dark' } } });\n\n// after\nconst userSchema = new mongoose.Schema({ prefs: Schema.Types.Mixed }, { strict: 'throw' });\nUser.updateOne({ _id }, { $set: { prefs: { theme: 'dark' } } });","handlingStrategy":"try-catch","validationCode":"// pre-check nested update paths against the schema when strict is 'throw'\nfunction assertPathsInSchema(update, schema) {\n  for (const [op, fields] of Object.entries(update)) {\n    for (const key of Object.keys(fields || {})) {\n      if (schema.path(key) == null && schema.nested[key] == null) {\n        throw new Error(`update path ${key} not in schema (strict: 'throw')`);\n      }\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try { await Model.updateOne(f, u); } catch (err) { if (err instanceof mongoose.Error.StrictModeError) { // err.message names the exact dotted path — add it to the schema, fix the typo, or re-run with { strict: false } } throw err; }","preventionTips":["Add fields to the schema before writing to them; use Mixed for free-form data","Check subdocument schemas for their own strict settings","Treat StrictModeError as a schema drift signal, not as noise to suppress"],"tags":["mongoose","update","strict-mode","schema","nested"],"backgroundTag":"mongoose-strict-mode","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}