Automattic/mongoose · error · StrictModeError

Field `${pathToCheck}` is not in schema and strict mode is s

Error message

Field `${pathToCheck}` is not in schema and strict mode is set to throw.

What it means

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.

Source

Thrown at lib/helpers/query/castUpdate.js:391

        }

        if (obj[key] === void 0) {
          delete obj[key];
          continue;
        }

        hasKeys = true;
      } else {
        const pathToCheck = (prefix + key);
        const v = schema._getPathType(pathToCheck);
        let _strict = strict;
        if (v?.schema && _strict == null) {
          _strict = v.schema.options.strict;
        }

        if (v.pathType === 'undefined') {
          if (_strict === 'throw') {
            throw new StrictModeError(pathToCheck);
          } else if (_strict) {
            delete obj[key];
            continue;
          }
        }

        // gh-2314
        // we should be able to set a schema-less field
        // to an empty object literal
        hasKeys |= walkUpdatePath(schema, val, op, options, context, filter, prefix + key) ||
          (utils.isObject(val) && utils.hasOwnKeys(val) === false);
      }
    } else {
      const isModifier = !isTopLevelNestedDollarPath && schematype == null &&
        (key === '$each' || key === '$or' || key === '$and' || key === '$in');
      const checkPath = isModifier ? prefix : fullPath;
      if (isModifier) {
        schematype = schema._getSchema(checkPath);

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Declare the path in the schema; use Schema.Types.Mixed (or a subdocument) for free-form data
  2. Fix typos in the nested path ('pref' vs 'prefs')
  3. Opt out deliberately per query: Model.updateOne(f, update, { strict: false }) — not recommended as a blanket fix

Example fix

// before: no 'prefs' path, schema strict: 'throw'
User.updateOne({ _id }, { $set: { prefs: { theme: 'dark' } } });

// after
const userSchema = new mongoose.Schema({ prefs: Schema.Types.Mixed }, { strict: 'throw' });
User.updateOne({ _id }, { $set: { prefs: { theme: 'dark' } } });
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check nested update paths against the schema when strict is 'throw'
function assertPathsInSchema(update, schema) {
  for (const [op, fields] of Object.entries(update)) {
    for (const key of Object.keys(fields || {})) {
      if (schema.path(key) == null && schema.nested[key] == null) {
        throw new Error(`update path ${key} not in schema (strict: 'throw')`);
      }
    }
  }
}

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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'.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/2ae3ee136cb80e64. Report an issue: GitHub.