Automattic/mongoose · error · StrictModeError

Field ` ` is not in schema and strict mode is set to throw.

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).

Solutions

  1. Fix the field name to match the schema path
  2. Add the field to the schema (Mixed if free-form)
  3. 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

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


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

Appendix: 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 '.' in

View on GitHub (pinned to 49cdab0136)