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

StrictModeError from the single-path branch of $set ($__set): the path you assigned does not resolve to any schema type - including dotted paths where some segment is missing - and the effective strict mode is 'throw'. Same write-time strict policy as the multi-key variant, reached via `doc.set('a.b', v)` style single-path calls after schema lookup and embedded-discriminator lookup both fail.

Source

Thrown at lib/document.js:1349

        // allow changes to sub paths of mixed types
        mixed = true;
        break;
      } else if (schema.$isSchemaMap && schema.$__schemaType instanceof MixedSchema && i < parts.length - 1) {
        // Map of mixed and not the last element in the path resolves to mixed
        mixed = true;
        schema = schema.$__schemaType;
        break;
      }
    }

    if (schema == null) {
      // Check for embedded discriminators
      schema = getEmbeddedDiscriminatorPath(this, path);
    }

    if (!mixed && !schema) {
      if (strict === 'throw') {
        throw new StrictModeError(path);
      }
      return this;
    }
  } else if (pathType === 'virtual') {
    schema = this.$__schema.virtualpath(path);
    schema.applySetters(val, this);
    return this;
  } else {
    schema = this.$__path(path);
  }

  // gh-4578, if setting a deeply nested path that doesn't exist yet, create it
  let cur = this._doc;
  let curPath = '';
  for (i = 0; i < parts.length - 1; ++i) {
    cur = cur instanceof Map ? cur.get(parts[i]) : cur[parts[i]];
    curPath += (curPath.length !== 0 ? '.' : '') + parts[i];
    if (!cur) {

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Fix the path so every segment exists in the schema
  2. Add the missing nested path to the schema
  3. Validate dynamic paths against `model.schema.path(p)` before calling set()
  4. Use `strict: true` to drop unknown paths silently instead of throwing

Example fix

// before
doc.set('address.stret', 'x'); // strict: 'throw' -> StrictModeError (typo)

// after
doc.set('address.street', 'x');
// for dynamic paths, validate first:
if (doc.constructor.schema.path(userPath) != null) doc.set(userPath, value);
Defensive patterns

Strategy: validation

Validate before calling

// Validate dynamic dotted paths before single-path set()
const schemaType = doc.constructor.schema.path(userPath);
if (schemaType == null && doc.constructor.schema.pathType(userPath) !== 'virtual') {
  throw new Error(`Refusing to set unknown path ${userPath}`);
}
doc.set(userPath, value);

Type guard

const isSettablePath = (doc, p) =>
  doc.constructor.schema.path(p) != null || doc.constructor.schema.pathType(p) === 'virtual';

Try / catch

try {
  doc.set(userPath, value);
} catch (err) {
  if (err instanceof mongoose.Error.StrictModeError) {
    // userPath does not resolve in the schema; reject the request field
  } else { throw err; }
}

Prevention

When it happens

Trigger: `doc.set('nested.unknown', v)` or `doc.set('typoPath', v)` under `strict: 'throw'` when `$__schema.path(path)` returns null; building paths dynamically from user input (e.g. PATCH endpoints mapping JSON paths straight to set()) so arbitrary segments reach the document.

Common situations: Dotted-path typos; nested paths whose parent was renamed in a refactor; generic REST wrappers that trust client-supplied path strings.

Related errors


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