Automattic/mongoose · error · StrictModeError

Path "${path}" is not in schema and strictQuery is 'throw'.

Error message

Path "${path}" is not in schema and strictQuery is 'throw'.

What it means

strictQuery controls how mongoose handles query conditions on paths missing from the schema. When it resolves to 'throw', cast() raises StrictModeError naming the path instead of ignoring the condition (plain true would silently delete it). This fires from find/update calls whose filter references an unknown path.

Source

Thrown at lib/cast.js:304

            _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
          );
        } else {
          const ks = Object.keys(val);
          let $cond;

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Fix the filter: add the field to the schema or correct the typo
  2. Allow unmodeled filters per query with .setOptions({ strictQuery: false }) or globally with mongoose.set('strictQuery', false)
  3. Whitelist filter keys against Object.keys(Model.schema.paths) before querying

Example fix

// before
const schema = new Schema({ name: String }, { strictQuery: 'throw' });
await Model.find({ nam: 'x' }); // typo -> throws

// after
await Model.find({ name: 'x' });
Defensive patterns

Strategy: validation

Validate before calling

function pickKnownFilterKeys(Model, filter) {
  const out = {};
  for (const k of Object.keys(filter)) {
    if (k in Model.schema.paths || k.startsWith('$')) out[k] = filter[k];
  }
  return out;
}
await Model.find(pickKnownFilterKeys(Model, req.query));

Try / catch

try {
  await Model.find(filter);
} catch (err) {
  if (err.name === 'StrictModeError' && /strictQuery/.test(err.message)) {
    // err.path is the unknown filter field; whitelist it, fix the typo, or relax strictQuery
  }
  throw err;
}

Prevention

When it happens

Trigger: Model.find({ notInSchema: 1 }) with schema or query strictQuery: 'throw'; Model.findOneAndUpdate({ typoField: 'x' }, update) with the same setting; mongoose.set('strictQuery', 'throw') globally combined with user-supplied filters.

Common situations: Migrations between mongoose majors where strictQuery defaults changed, so previously-ignored filters start throwing once 'throw' is set; search endpoints forwarding arbitrary filter keys; renamed schema fields while old clients send old names; enabling 'throw' deliberately to catch filter typos.

Related errors


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