Automattic/mongoose · error · StrictModeError

Field `${path}` is not in schema and strict mode is set to t

Error message

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

What it means

While casting an upsert, mongoose found a path that is not in the schema and strict mode resolved to 'throw'. StrictModeError exists to surface unknown fields instead of silently dropping them; the upsert flag makes any truthy strict setting fatal, and 'throw' produces this default message naming the field.

Source

Thrown at lib/cast.js:299

                  value = value.toObject({ virtuals: false });
                }
              }
            }

            _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,

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Declare the field in the schema (or fix the typo) so the path is known
  2. Strip unknown keys from the update document before calling updateOne with upsert: true
  3. Allow it for this call only: Model.updateOne(filter, update, { upsert: true, strict: false })
  4. Store genuinely schemaless extras under a declared Mixed path instead of top level

Example fix

// before
const schema = new Schema({ name: String }, { strict: 'throw' });
await Model.updateOne({ name: 'x' }, { name: 'x', counter: 1 }, { upsert: true });

// after
const schema = new Schema({ name: String, counter: Number }, { strict: 'throw' });
await Model.updateOne({ name: 'x' }, { name: 'x', counter: 1 }, { upsert: true });
Defensive patterns

Strategy: validation

Validate before calling

function findUnknownPaths(Model, doc) {
  return Object.keys(doc).filter(
    k => !(k in Model.schema.paths) && !Model.schema.nested[k]
  );
}
const unknown = findUnknownPaths(Model, update);
if (unknown.length > 0 && opts.upsert) {
  throw new Error(`Refusing upsert with unknown paths: ${unknown.join(', ')}`);
}

Try / catch

try {
  await Model.updateOne(filter, update, { upsert: true });
} catch (err) {
  if (err.name === 'StrictModeError') {
    // err.path names the unknown field; add it to the schema or delete it from `update`
  }
  throw err;
}

Prevention

When it happens

Trigger: Model.updateOne(filter, { notInSchema: 1 }, { upsert: true }) on a schema defined with { strict: 'throw' }; the same via findOneAndUpdate; passing { strict: 'throw' } inside the options of a single call.

Common situations: Upserting API payloads that carry extra metadata (tenant id, client version) never added to the schema; field-name typos; payloads shared with insert paths that ran under strict: false; enabling strict: 'throw' during a data-hygiene audit.

Related errors


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