{"record":{"id":"4e3ea9a6f20cec46","repo":"Automattic/mongoose","slug":"field-prefix-key-is-not-in-schema-and-stric","errorCode":null,"errorMessage":"Field `${prefix}${key}` 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":443,"sourceCode":"          schematype = _res.schematype;\n          pathDetails = _res.type;\n        }\n      }\n\n      let isStrict = strict;\n      if (pathDetails?.schema && strict == null) {\n        isStrict = pathDetails.schema.options.strict;\n      }\n\n      const skip = isStrict &&\n        !schematype &&\n        !/real|nested/.test(pathDetails.pathType);\n\n      if (skip) {\n        // Even if strict is `throw`, avoid throwing an error because of\n        // virtuals because of #6731\n        if (isStrict === 'throw' && schema.virtuals[checkPath] == null) {\n          throw new StrictModeError(prefix + key);\n        } else {\n          delete obj[key];\n        }\n      } else {\n        if (op === '$rename') {\n          if (obj[key] == null) {\n            throw new CastError('String', obj[key], `${prefix}${key}.$rename`);\n          }\n          const schematype = new SchemaString(`${prefix}${key}.$rename`, null, null, schema);\n          obj[key] = schematype.castForQuery(null, obj[key], context);\n          continue;\n        }\n\n        try {\n          if (prefix.length === 0 || key.indexOf('.') === -1) {\n            obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);\n          } else if (isStrict !== false || schematype != null) {\n            // Setting a nested dotted path that's in the schema. We don't allow paths with '.' in","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/helpers/query/castUpdate.js#L425-L461","documentation":"The leaf-value counterpart of the nested StrictModeError: when a (possibly dotted) update key resolves to no schematype and pathDetails.pathType is neither 'real' nor 'nested', strict mode says to skip the key; if the effective strict value is 'throw' Mongoose throws StrictModeError(prefix + key) instead of deleting it. Virtuals are explicitly exempted so updates that try to set a virtual are silently stripped rather than throwing (gh-6731).","triggerScenarios":"Schema with strict: 'throw' plus Model.updateOne(f, { $set: { nmae: 'A' } }) (typo path); setting a non-virtual, non-schema field to a scalar value; per-query strict: 'throw' via Model.updateOne(f, upd, { strict: 'throw' }).","commonSituations":"Typos in field names that strict: true would silently drop; fields added directly in MongoDB by other services but absent from the Mongoose schema; enabling strict: 'throw' to catch such mistakes and then hitting legacy updates.","solutions":["Fix the field name to match the schema path","Add the field to the schema (Mixed if free-form)","Allow schemaless writes intentionally with Model.updateOne(f, upd, { strict: false }) or schema strict: false"],"exampleFix":"// before: 'nmae' typo, schema strict: 'throw'\nUser.updateOne({ _id }, { $set: { nmae: 'Alice' } });\n\n// after\nUser.updateOne({ _id }, { $set: { name: 'Alice' } });","handlingStrategy":"validation","validationCode":"// fail fast on unknown top-level update keys under strict:'throw'\nfunction assertUpdateKeys(update, schema) {\n  for (const [op, fields] of Object.entries(update)) {\n    if (!op.startsWith('$')) continue;\n    for (const key of Object.keys(fields || {})) {\n      if (schema.path(key) == null && schema.virtuals[key] == null) {\n        throw new Error(`unknown update key ${key} under ${op}`);\n      }\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try { await Model.updateOne(f, u); } catch (err) { if (err instanceof mongoose.Error.StrictModeError) { /* message names the bad path — fix typo or add to schema; virtuals are exempt */ } throw err; }","preventionTips":["Derive update field names from shared constants to avoid typos","Use strict: 'throw' in development to surface unknown paths early","Keep the Mongoose schema in sync with fields other services write"],"tags":["mongoose","update","strict-mode","schema","typo"],"backgroundTag":"mongoose-strict-mode","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}