Automattic/mongoose · error · MongooseError
Query.prototype.find() no longer accepts a callback
Error message
Query.prototype.find() no longer accepts a callback
What it means
Mongoose 7.0 removed callback-style execution from all query methods; Query.prototype.find() throws immediately if its first argument or the second positional argument (arguments[1]) is a function. The throw happens at query-construction time, before any database call, so legacy code like Model.find({}, cb) fails fast instead of silently never invoking the callback.
Source
Thrown at lib/query.js:2550
/**
* Find all documents that match `selector`. The result will be an array of documents.
*
* If there are too many documents in the result to fit in memory, use
* [`Query.prototype.cursor()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.cursor())
*
* #### Example:
*
* const arr = await Movie.find({ year: { $gte: 1980, $lte: 1989 } });
*
* @param {object|ObjectId} [filter] mongodb filter. If not specified, returns all documents.
* @return {Query} this
* @api public
*/
Query.prototype.find = function(conditions) {
if (typeof conditions === 'function' ||
typeof arguments[1] === 'function') {
throw new MongooseError('Query.prototype.find() no longer accepts a callback');
}
this.op = 'find';
if (canMerge(conditions)) {
this.merge(conditions);
prepareDiscriminatorCriteria(this);
} else if (conditions != null) {
this.error(new ObjectParameterError(conditions, 'filter', 'find'));
}
return this;
};
/**
* Merges another Query or conditions object into this one.
*View on GitHub (pinned to 49cdab0136)
Solutions
- Use async/await: const docs = await Model.find({})
- Or promise chaining: Model.find({}).then(docs => ...).catch(err => ...)
- Grep the codebase for .find( calls with a trailing function argument and remove the callbacks; follow the Mongoose 6 to 7 migration guide
Example fix
// before (mongoose 6 and earlier)
Model.find({ active: true }, (err, docs) => {
if (err) return next(err);
res.json(docs);
});
// after (mongoose 7/8)
try {
const docs = await Model.find({ active: true });
res.json(docs);
} catch (err) {
next(err);
} Defensive patterns
Strategy: validation
Validate before calling
// Optional dev-time wrapper that fails fast with a clearer message
function findSafe(model, filter, options) {
if ([filter, options].some(v => typeof v === 'function')) {
throw new Error('find() is promise-only in Mongoose 7+; remove the callback');
}
return model.find(filter, options);
} Type guard
const isLegacyCallback = (v) => typeof v === 'function';
Try / catch
try {
const docs = await Model.find(filter);
} catch (err) {
if (err?.message?.includes('no longer accepts a callback')) {
// a call site still uses the removed callback signature: fix it there
}
throw err;
} Prevention
- Search for 'err =>' near Mongoose calls when upgrading versions
- Adopt async/await uniformly; Mongoose 7+ has no callback path
- Keep model access in typed wrappers so stray callbacks are caught in code review
When it happens
Trigger: Model.find({}, (err, docs) => {...}); Model.find(cb); passing a function in the filter slot (.find(someMapper)); wrappers built on the `async` library (async.waterfall) that forward nodeback callbacks positionally.
Common situations: Upgrading mongoose 6 to 7/8 without migrating callbacks (deprecated in 6, removed in 7); old tutorials and Stack Overflow snippets; large legacy codebases where a single un-migrated call throws on the first request after deploy.
Related errors
- Query.prototype.findOne() no longer accepts a callback
- Query.prototype.estimatedDocumentCount() no longer accepts a
- Query.prototype.countDocuments() no longer accepts a callbac
- Query.prototype.distinct() no longer accepts a callback
- Query.prototype.deleteOne() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/e9910197116bb225.
Report an issue: GitHub.