Automattic/mongoose · error · StrictModeError
Field `${prefix}${key}` is not in schema and strict mode is
Error message
Field `${prefix}${key}` is not in schema and strict mode is set to throw. What it means
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).
Source
Thrown at lib/helpers/query/castUpdate.js:443
schematype = _res.schematype;
pathDetails = _res.type;
}
}
let isStrict = strict;
if (pathDetails?.schema && strict == null) {
isStrict = pathDetails.schema.options.strict;
}
const skip = isStrict &&
!schematype &&
!/real|nested/.test(pathDetails.pathType);
if (skip) {
// Even if strict is `throw`, avoid throwing an error because of
// virtuals because of #6731
if (isStrict === 'throw' && schema.virtuals[checkPath] == null) {
throw new StrictModeError(prefix + key);
} else {
delete obj[key];
}
} else {
if (op === '$rename') {
if (obj[key] == null) {
throw new CastError('String', obj[key], `${prefix}${key}.$rename`);
}
const schematype = new SchemaString(`${prefix}${key}.$rename`, null, null, schema);
obj[key] = schematype.castForQuery(null, obj[key], context);
continue;
}
try {
if (prefix.length === 0 || key.indexOf('.') === -1) {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} else if (isStrict !== false || schematype != null) {
// Setting a nested dotted path that's in the schema. We don't allow paths with '.' inView on GitHub (pinned to 49cdab0136)
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
Example fix
// before: 'nmae' typo, schema strict: 'throw'
User.updateOne({ _id }, { $set: { nmae: 'Alice' } });
// after
User.updateOne({ _id }, { $set: { name: 'Alice' } }); Defensive patterns
Strategy: validation
Validate before calling
// fail fast on unknown top-level update keys under strict:'throw'
function assertUpdateKeys(update, schema) {
for (const [op, fields] of Object.entries(update)) {
if (!op.startsWith('$')) continue;
for (const key of Object.keys(fields || {})) {
if (schema.path(key) == null && schema.virtuals[key] == null) {
throw new Error(`unknown update key ${key} under ${op}`);
}
}
}
} Try / catch
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; } Prevention
- 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
When it happens
Trigger: 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' }).
Common situations: 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.
Related errors
- Field `${pathToCheck}` is not in schema and strict mode is s
- Field `${path}` is not in schema and strict mode is set to t
- Path "${path}" is not in schema, strict mode is `true`, and
- Field `${path}` is not in schema and strictRead is set to th
- Field `${i}` is not in schema and strict mode is set to thro
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/4e3ea9a6f20cec46.
Report an issue: GitHub.