Automattic/mongoose · error · MongooseError

`Model.${fnName}()` cannot run without a model as `this`. Ma

Error message

`Model.${fnName}()` cannot run without a model as `this`. Make sure you are not calling `new Model.${fnName}()`

What it means

Second branch of `_checkContext`: the receiver is an object but lacks the internal `modelSymbol` property, which every real compiled mongoose Model carries. The canonical trigger is `new Model.someStatic()` — e.g. `new Model.discriminator()` — where `new` boxes the call on a fresh object without the symbol. The comment in the source says this check exists precisely because `new Model.discriminator()` otherwise produces an incomprehensible error.

Source

Thrown at lib/model.js:1070

  }

  return d;
};

/**
 * Make sure `this` is a model
 * @api private
 */

function _checkContext(ctx, fnName) {
  // Check context, because it is easy to mistakenly type
  // `new Model.discriminator()` and get an incomprehensible error
  if (ctx == null || ctx === global) {
    throw new MongooseError('`Model.' + fnName + '()` cannot run without a ' +
      'model as `this`. Make sure you are calling `MyModel.' + fnName + '()` ' +
      'where `MyModel` is a Mongoose model.');
  } else if (ctx[modelSymbol] == null) {
    throw new MongooseError('`Model.' + fnName + '()` cannot run without a ' +
      'model as `this`. Make sure you are not calling ' +
      '`new Model.' + fnName + '()`');
  }
}

// Model (class) features

/*!
 * Give the constructor the ability to emit events.
 */

for (const i in EventEmitter.prototype) {
  Model[i] = EventEmitter.prototype[i];
}

/**
 * This function is responsible for initializing the underlying connection in MongoDB based on schema options.
 * This function performs the following operations:

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Remove `new`: `Event.discriminator('Click', schema)` returns the model directly
  2. Keep `new` only for the actual constructor: `const doc = new Event({...})`
  3. If wrapping statics, call them off the model: `MyModel.findOne(...)`

Example fix

// before
const Clicked = new Event.discriminator('Clicked', clickedSchema);

// after
const Clicked = Event.discriminator('Clicked', clickedSchema);
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard in dev builds: model statics must never be invoked with `new`
const safeStatic = (Model, fnName, ...args) => {
  if (!isMongooseModel(Model)) throw new TypeError('Pass the model, not an instance/plain object');
  return Model[fnName](...args); // note: no `new` on statics
};

Type guard

function isMongooseModel(v) {
  return typeof v === 'function' &&
    typeof v.modelName === 'string' &&
    v.db != null &&
    typeof v.findOne === 'function';
}

Prevention

When it happens

Trigger: `const d = new Event.discriminator('Click', schema);`; `new User.init();`; any Model static invoked with `new` because the capitalized name reads like a class constructor; also calling a static with `.call(somePlainObject, ...)`.

Common situations: Copy-paste from code that uses classes with static factories; IDE autocompletion inserting `new` on capitalized methods; migrating from patterns like `new Model.findById()`. Note: only statics go through _checkContext — document methods (`new Model({...})`) are the legitimate constructor use.

Related errors


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