Automattic/mongoose · error · MongooseError

Path `${path}` is not in the schema

Error message

Path `${path}` is not in the schema

What it means

While copying paths, Schema.prototype.pick() looks each requested path up via this.path(path); if the schematype is null (and the path is not nested and not an encrypted field), Mongoose throws 'Path `x` is not in the schema'. The input list must name existing top-level or nested paths exactly — there is no wildcard or silent skip.

Source

Thrown at lib/schema.js:543

      'got "' + typeof paths + '"');
  }

  for (const path of paths) {
    if (this._hasEncryptedField(path)) {
      const encrypt = this.encryptedFields[path];
      const schemaType = this.path(path);
      newSchema.add({
        [path]: {
          encrypt,
          [this.options.typeKey]: schemaType
        }
      });
    } else if (this.nested[path]) {
      newSchema.add({ [path]: get(this.tree, path) });
    } else {
      const schematype = this.path(path);
      if (schematype == null) {
        throw new MongooseError('Path `' + path + '` is not in the schema');
      }
      newSchema.add({ [path]: schematype });
    }
  }

  if (!this._hasEncryptedFields()) {
    newSchema.options.encryptionType = null;
  }

  return newSchema;
};

/**
 * Returns a new schema that has the `paths` from the original schema, minus the omitted ones.
 *
 * This method is analagous to [Lodash's `omit()` function](https://lodash.com/docs/#omit) for Mongoose schemas.
 *
 * #### Example:

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Fix the list to contain only real paths: verify with `schema.path('name')` or `Object.keys(schema.paths)`.
  2. Filter dynamically sourced lists against existing paths before calling pick.
  3. After renames, update every pick list; add a unit test that calls pick() on your production list.

Example fix

// before
const sub = schema.pick(['name', 'nickname']); // throws if 'nickname' is not defined

// after
const wanted = ['name', 'nickname'].filter(p => schema.path(p) != null);
const sub = schema.pick(wanted);
Defensive patterns

Strategy: validation

Validate before calling

function pickExisting(schema, wanted) {
  const valid = wanted.filter(p => schema.path(p) != null || schema.nested[p]);
  return schema.pick(valid);
}

Type guard

const pathExists = (schema, p) => schema.path(p) != null || Boolean(schema.nested[p]);

Try / catch

try { return schema.pick(wanted); } catch (err) { if (err instanceof mongoose.Error && /is not in the schema/.test(err.message)) { return schema.pick(wanted.filter(p => schema.path(p) != null)); } throw err; }

Prevention

When it happens

Trigger: `schema.pick(['nonexistent'])`; casing/spelling mismatches ('Name' vs 'name'); picking dotted paths that do not exist; picking paths that were removed via schema.remove(); deriving the pick list from user input or a stale constant.

Common situations: Field lists kept in a separate constant that drifts from the schema after renames; generating pick lists from API allowlists without syncing to schema changes; picking subdocument paths after a schema refactor.

Related errors


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