Automattic/mongoose · error · MongooseError
Model.find() no longer accepts a callback
Error message
Model.find() no longer accepts a callback
What it means
Model.find(conditions, projection, options) is the core query static; Mongoose 7 removed its callback form, so a function in any of the first four argument slots throws synchronously and no Query is returned. The result comes from awaiting the Query or calling .exec().
Source
Thrown at lib/model.js:2126
* await MyModel.find({ name: /john/i }, 'name friends').exec();
*
* // passing options
* await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
*
* @param {object|ObjectId} filter
* @param {object|string|string[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
* @see query casting https://mongoosejs.com/docs/tutorials/query_casting.html
* @api public
*/
Model.find = function find(conditions, projection, options) {
_checkContext(this, 'find');
if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function' || typeof arguments[3] === 'function') {
throw new MongooseError('Model.find() no longer accepts a callback');
}
const mq = new this.Query({}, {}, this, this.$__collection);
mq.select(projection);
mq.setOptions(options);
return mq.find(conditions);
};
/**
* Finds a single document by its _id field. `findById(id)` is equivalent to `findOne({ _id: id })`.
*
* The `id` is cast based on the Schema before sending the command.
*
* This function triggers the following middleware.
*
* - `findOne()`
*View on GitHub (pinned to 49cdab0136)
Solutions
- Await the query: `const users = await User.find({ age: { $gte: 18 } }, 'name');`
- Or `User.find({}).exec().then(...)`
- Automate the sweep: grep for `\.find\(.*=>` and `\.find\([^)]*,\s*function` and migrate all matches in one pass
Example fix
// before
User.find({ role: 'admin' }, (err, admins) => { if (err) throw err; ... });
// after
const admins = await User.find({ role: 'admin' }); Defensive patterns
Strategy: validation
Validate before calling
const isFn = (a) => typeof a === 'function';
if ([conditions, projection, options].some(isFn)) {
throw new TypeError('find() is promise-only');
}
const docs = await User.find(conditions, projection, options); Prevention
- Do the callback-to-promise migration as its own commit before bumping mongoose major — find() has the most call sites
- Enable no-floating-promises in ESLint so an un-awaited Query is caught statically
When it happens
Trigger: `User.find({ age: { $gte: 18 } }, 'name', (err, docs) => ...)`; `User.find(cb)`; any of the 4 positional slots receiving a function.
Common situations: The single most common hit when upgrading mongoose 6 to 7+: find() calls are ubiquitous; old tutorials and generated CRUD code are callback-based.
Related errors
- Model.findById() no longer accepts a callback
- Model.findOne() no longer accepts a callback
- Model.findOneAndUpdate() no longer accepts a callback
- Model.init() no longer accepts a callback
- Model.createCollection() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/def91720d222128f.
Report an issue: GitHub.