Automattic/mongoose · error · StrictModeError
Path "${path}" is not in schema, strict mode is `true`, and
Error message
Path "${path}" is not in schema, strict mode is `true`, and upsert is `true`. What it means
With strict true (the default) and upsert true, mongoose treats schema-unknown paths as fatal rather than stripping them: cast() checks the upsert+strict combination first and throws StrictModeError with this message. A non-upsert update would silently delete the unknown path; the upsert makes it an error.
Source
Thrown at lib/cast.js:301
}
}
_cast(value, numbertype, context);
continue;
}
}
if (schema.nested[path]) {
continue;
}
const strict = 'strict' in options ? options.strict : schema.options.strict;
const strictQuery = getStrictQuery(options, schema._userProvidedOptions, schema.options, context);
if (options.upsert && strict) {
if (strict === 'throw') {
throw new StrictModeError(path);
}
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
'schema, strict mode is `true`, and upsert is `true`.');
} if (strictQuery === 'throw') {
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
'schema and strictQuery is \'throw\'.');
} else if (strictQuery) {
delete obj[path];
}
} else if (val == null) {
continue;
} else if (utils.isPOJO(val)) {
any$conditionals = Object.keys(val).some(isOperator);
if (!any$conditionals) {
obj[path] = schematype.castForQuery(
null,
val,
context
);View on GitHub (pinned to 49cdab0136)
Solutions
- Add the field to the schema
- Strip unknown keys from the update before the call (pick only modeled fields)
- Opt out per call: Model.updateOne(filter, update, { upsert: true, strict: false })
- As a last resort set { strict: false } on the schema -- note this disables the guard for all writes
Example fix
// before
await Model.updateOne({ name: 'x' }, { name: 'x', extra: 1 }, { upsert: true }); // `extra` not in schema
// after -- declare `extra` in the schema, or allow it for this call only:
await Model.updateOne({ name: 'x' }, { name: 'x', extra: 1 }, { upsert: true, strict: false }); Defensive patterns
Strategy: validation
Validate before calling
function pickKnownPaths(Model, doc) {
const out = {};
for (const k of Object.keys(doc)) {
if (k in Model.schema.paths || k.startsWith('$')) out[k] = doc[k];
}
return out;
}
await Model.updateOne(filter, pickKnownPaths(Model, update), { upsert: true }); Try / catch
try {
await Model.updateOne(filter, update, { upsert: true });
} catch (err) {
if (err.name === 'StrictModeError' && err.message.includes('upsert')) {
// either declare the path in the schema, strip it, or set strict: false for this call
}
throw err;
} Prevention
- Map update payloads explicitly from transport DTOs to modeled fields
- When introducing new client fields, ship the schema change first
- Use strict: 'throw' in development to catch unknown paths early
When it happens
Trigger: Model.updateOne(filter, { unknownField: 1 }, { upsert: true }) on a default-strict schema; findOneAndUpdate(..., { upsert: true }) whose update contains client-added fields; $setOnInsert keys that are not modeled.
Common situations: Newer clients sending new fields before the schema is updated; payloads carrying metadata keys not modeled; sharing one object between save() and upsert code paths; renaming schema fields while old writers keep persisting the old name.
Related errors
- Field `${path}` is not in schema and strict mode is set to t
- 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
- Field `${key}` is not in schema and strict mode is set to th
- Field `${path}` is not in schema and strict mode is set to t
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/60779e719baec022.
Report an issue: GitHub.