Automattic/mongoose · error · MongooseError

Model.distinct() no longer accepts a callback

Error message

Model.distinct() no longer accepts a callback

What it means

Model.distinct(field, conditions, options) runs a distinct command on one field with casting and returns a Query resolving to the array of distinct values. Callbacks were removed in Mongoose 7; a function in any of the first three slots throws before the Query is created.

Source

Thrown at lib/model.js:2297

/**
 * Creates a Query for a `distinct` operation.
 *
 * #### Example:
 *
 *     const query = Link.distinct('url');
 *     query.exec();
 *
 * @param {string} field
 * @param {object} [conditions] optional
 * @param {object} [options] optional
 * @return {Query}
 * @api public
 */

Model.distinct = function distinct(field, conditions, options) {
  _checkContext(this, 'distinct');
  if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {
    throw new MongooseError('Model.distinct() no longer accepts a callback');
  }

  const mq = new this.Query({}, {}, this, this.$__collection);
  if (options != null) {
    mq.setOptions(options);
  }

  return mq.distinct(field, conditions);
};

/**
 * Creates a Query, applies the passed conditions, and returns the Query.
 *
 * For example, instead of writing:
 *
 *     User.find({ age: { $gte: 21, $lte: 65 } });
 *
 * we can instead write:

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Await it: `const roles = await User.distinct('role');`
  2. Migrate the surrounding callback flow to async/await at the same time to avoid partial rewrites
  3. Add `distinct\(` to the migration grep list alongside find/findOne/count

Example fix

// before
User.distinct('role', (err, roles) => { ... });

// after
const roles = await User.distinct('role');
Defensive patterns

Strategy: validation

Validate before calling

const isFn = (a) => typeof a === 'function';
if ([field, conditions, options].some(isFn)) {
  throw new TypeError('distinct() is promise-only');
}
const values = await User.distinct(field, conditions);

Prevention

When it happens

Trigger: `User.distinct('role', {}, cb)`; `User.distinct('email', cb)`; report/export builders written callback-style.

Common situations: Aggregation-lite helpers (distinct roles, tags) from older codebases; migration sweep gaps for less-common statics.

Related errors


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