{"record":{"id":"2cb14e44901f39b0","repo":"Automattic/mongoose","slug":"model-distinct-no-longer-accepts-a-callback","errorCode":null,"errorMessage":"Model.distinct() no longer accepts a callback","messagePattern":"Model\\.distinct\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":2297,"sourceCode":"/**\n * Creates a Query for a `distinct` operation.\n *\n * #### Example:\n *\n *     const query = Link.distinct('url');\n *     query.exec();\n *\n * @param {string} field\n * @param {object} [conditions] optional\n * @param {object} [options] optional\n * @return {Query}\n * @api public\n */\n\nModel.distinct = function distinct(field, conditions, options) {\n  _checkContext(this, 'distinct');\n  if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {\n    throw new MongooseError('Model.distinct() no longer accepts a callback');\n  }\n\n  const mq = new this.Query({}, {}, this, this.$__collection);\n  if (options != null) {\n    mq.setOptions(options);\n  }\n\n  return mq.distinct(field, conditions);\n};\n\n/**\n * Creates a Query, applies the passed conditions, and returns the Query.\n *\n * For example, instead of writing:\n *\n *     User.find({ age: { $gte: 21, $lte: 65 } });\n *\n * we can instead write:","sourceCodeStart":2279,"sourceCodeEnd":2315,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L2279-L2315","documentation":"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.","triggerScenarios":"`User.distinct('role', {}, cb)`; `User.distinct('email', cb)`; report/export builders written callback-style.","commonSituations":"Aggregation-lite helpers (distinct roles, tags) from older codebases; migration sweep gaps for less-common statics.","solutions":["Await it: `const roles = await User.distinct('role');`","Migrate the surrounding callback flow to async/await at the same time to avoid partial rewrites","Add `distinct\\(` to the migration grep list alongside find/findOne/count"],"exampleFix":"// before\nUser.distinct('role', (err, roles) => { ... });\n\n// after\nconst roles = await User.distinct('role');","handlingStrategy":"validation","validationCode":"const isFn = (a) => typeof a === 'function';\nif ([field, conditions, options].some(isFn)) {\n  throw new TypeError('distinct() is promise-only');\n}\nconst values = await User.distinct(field, conditions);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include less-common statics (distinct, countDocuments) in the migration checklist — they are the ones that slip through","Prefer promise-based reporting utilities so callback helpers from legacy libs are not reused"],"tags":["mongoose","callback-removed","promise","distinct","migration"],"backgroundTag":"mongoose-callback-removed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}