Automattic/mongoose · error · StrictModeError

Field `${i}` is not in schema and strict mode is set to thro

Error message

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

What it means

StrictModeError thrown during hydration when the caller explicitly passed `strict: 'throw'` in the hydration options (e.g. `MyModel.hydrate(obj, null, { strict: 'throw' })`) and the object contains a field with no schema path. Schema-level `strict: 'throw'` deliberately does NOT apply to documents loaded from the db - only this explicit per-call option triggers the throw, for backwards compatibility.

Source

Thrown at lib/document.js:823

    } else if (!schemaType) {
      // Handle strictRead: filter unknown fields during document hydration from DB
      if (strictRead === 'throw') {
        throw new StrictModeError(path, 'Field `' + path + '` is not in schema and strictRead is set to throw.');
      } else if (strictRead === true) {
        // Skip this field - do not store in _doc
        continue;
      }
      doc[i] = value;
      if (!strict && !prefix) {
        self[i] = value;
      } else if (opts?.virtuals && (i in docSchema.virtuals)) {
        self[i] = value;
      } else if (opts?.strict === 'throw') {
        // Only use strict: 'throw' semantics if explicit `strict: 'throw'` option
        // passed in, like via `MyModel.hydrate(obj, null, { strict: 'throw' })`
        // This is for backwards compatibility - strict: 'throw' at the schema level
        // does not apply to documents loaded from the db.
        throw new StrictModeError(i);
      }
    } else {
      // Retain order when overwriting defaults
      if (Object.hasOwn(doc, i) && value !== void 0 && !opts.hydratedPopulatedDocs) {
        delete doc[i];
      }
      if (value === null) {
        doc[i] = schemaType._castNullish(null);
      } else if (value !== undefined) {
        const wasPopulated = value.$__ == null ? null : value.$__.wasPopulated;

        if (schemaType && !wasPopulated && !opts.hydratedPopulatedDocs) {
          try {
            if (opts?.setters) {
              // Call applySetters with `init = false` because otherwise setters are a noop
              const overrideInit = false;
              doc[i] = schemaType.applySetters(value, self, overrideInit, null, opts);
            } else {

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Drop `strict: 'throw'` from the hydrate options so unknown keys are tolerated
  2. Whitelist keys against the schema before hydrating
  3. Add the extra fields to the schema
  4. Use the dedicated `strictRead` option if you want a read-time policy

Example fix

// before
const doc = MyModel.hydrate(raw, null, { strict: 'throw' }); // raw has extra keys -> StrictModeError

// after
const paths = new Set(Object.keys(MyModel.schema.paths).concat(['_id']));
const clean = Object.fromEntries(Object.entries(raw).filter(([k]) => paths.has(k)));
const doc = MyModel.hydrate(clean, null, { strict: 'throw' });
Defensive patterns

Strategy: try-catch

Validate before calling

// Strip unknown keys before hydrating with strict: 'throw'
const known = new Set(Object.keys(MyModel.schema.paths).concat(['_id']));
const clean = Object.fromEntries(Object.entries(raw).filter(([k]) => known.has(k)));
const doc = MyModel.hydrate(clean, null, { strict: 'throw' });

Try / catch

try {
  const doc = MyModel.hydrate(raw, null, { strict: 'throw' });
} catch (err) {
  if (err instanceof mongoose.Error.StrictModeError) {
    // input object has extra keys; whitelist them or drop the strict option
  } else { throw err; }
}

Prevention

When it happens

Trigger: Calling `MyModel.hydrate(obj, null, { strict: 'throw' })` (or any init path where opts.strict === 'throw') with an object that has keys not defined in the schema.

Common situations: Teams porting write-time `strict: 'throw'` checks to hydrate(); hydrating raw aggregation output or third-party data containing extra keys; Mongoose 7/8 behavior where schema-level strict: 'throw' no longer applies to db-loaded documents.

Related errors


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