Automattic/mongoose · error · Error

You have a method and a property in your schema both named "

Error message

You have a method and a property in your schema both named "${method}"

What it means

applyMethods copies schema.methods onto the model prototype at compile time. If a schema path (field) already exists in schema.tree with the same name, defining both a method and a property with one name would make one shadow the other on every document, so Mongoose throws Error('You have a method and a property in your schema both named ...') when Object.hasOwn(schema.tree, method) is true.

Source

Thrown at lib/helpers/model/applyMethods.js:32

module.exports = function applyMethods(model, schema) {
  const Model = require('../../model');

  function apply(method, schema) {
    Object.defineProperty(model.prototype, method, {
      get: function() {
        const h = {};
        for (const k in schema.methods[method]) {
          h[k] = schema.methods[method][k].bind(this);
        }
        return h;
      },
      configurable: true
    });
  }
  for (const method of Object.keys(schema.methods)) {
    const fn = schema.methods[method];
    if (Object.hasOwn(schema.tree, method)) {
      throw new Error('You have a method and a property in your schema both ' +
        'named "' + method + '"');
    }

    // Avoid making custom methods if user sets a method to itself, e.g.
    // `schema.method(save, Document.prototype.save)`. Can happen when
    // calling `loadClass()` with a class that `extends Document`. See gh-12254
    if (typeof fn === 'function' &&
        Model.prototype[method] === fn) {
      delete schema.methods[method];
      continue;
    }

    if (schema.reserved[method] &&
        !get(schema, `methodOptions.${method}.suppressWarning`, false)) {
      utils.warn(`mongoose: the method name "${method}" is used by mongoose ` +
        'internally, overwriting it may cause bugs. If you\'re sure you know ' +
        'what you\'re doing, you can suppress this error by using ' +
        `\`schema.method('${method}', fn, { suppressWarning: true })\`.`);

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Rename the method (e.g. displayName() instead of name()) or rename the field.
  2. If you wanted a computed value, use a virtual: schema.virtual('upperName').get(function () {...}) - virtuals are the right tool for derived properties.
  3. With loadClass classes, rename class members that clash with schema paths.

Example fix

// before
const userSchema = new Schema({ name: String });
userSchema.methods.name = function () { return this.name.toUpperCase(); }; // collides with path 'name'

// after: differently-named method, or a virtual
userSchema.methods.displayName = function () { return this.name.toUpperCase(); };
// or
userSchema.virtual('upperName').get(function () { return this.name.toUpperCase(); });
Defensive patterns

Strategy: validation

Validate before calling

// detect method/path collisions before model compilation
function assertNoMethodPathCollisions(schema) {
  for (const method of Object.keys(schema.methods)) {
    if (Object.hasOwn(schema.tree, method)) {
      throw new Error(`method '${method}' collides with schema path of the same name`);
    }
  }
}
assertNoMethodPathCollisions(userSchema);
const User = mongoose.model('User', userSchema);

Prevention

When it happens

Trigger: const s = new Schema({ name: String }); s.methods.name = function () {...}; - any schema.methods key equal to an existing path name; class-based schemas via loadClass whose method or getter names collide with schema paths.

Common situations: Adding convenience accessors named exactly after the field (e.g. a method named password on a schema with a password path); ES class models (loadClass) with members clashing with schema fields; copy-pasting method sets between schemas.

Related errors


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