Automattic/mongoose · error · MongooseError
Query.prototype.findOneAndDelete() no longer accepts a callb
Error message
Query.prototype.findOneAndDelete() no longer accepts a callback
What it means
Query.prototype.findOneAndDelete(filter, options) throws when filter, options, or a third positional argument is a function — the Mongoose 7 promise-only rule. The throw happens while building the query, before the delete command is sent, so legacy callback invocations fail fast.
Source
Thrown at lib/query.js:3685
*
* @method findOneAndDelete
* @memberOf Query
* @param {object} [filter]
* @param {object} [options]
* @param {boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/ModifyResult.html) rather than just the document
* @param {boolean} [options.requireFilter=false] If true, throws an error if the filter is empty (`{}`)
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @return {Query} this
* @see findAndModify command https://www.mongodb.com/docs/manual/reference/command/findAndModify/
* @api public
*/
Query.prototype.findOneAndDelete = function(filter, options) {
if (typeof filter === 'function' ||
typeof options === 'function' ||
typeof arguments[2] === 'function') {
throw new MongooseError('Query.prototype.findOneAndDelete() no longer accepts a callback');
}
this.op = 'findOneAndDelete';
this._validate();
if (canMerge(filter)) {
this.merge(filter);
}
options && this.setOptions(options);
return this;
};
/**
* Execute a `findOneAndDelete()` query
*
* @return {Query} thisView on GitHub (pinned to 49cdab0136)
Solutions
- Use await: const doc = await Model.findOneAndDelete({ _id }); doc is null when nothing matched
- Wrap in try/catch for error handling
- Remove trailing callbacks from all findOneAndDelete call sites during upgrade
Example fix
// before
Model.findOneAndDelete({ _id }, (err, doc) => {
if (err) return next(err);
res.json(doc);
});
// after
try {
const doc = await Model.findOneAndDelete({ _id });
res.json(doc);
} catch (err) {
next(err);
} Defensive patterns
Strategy: validation
Validate before calling
function findOneAndDeleteSafe(model, filter, options) {
if ([filter, options].some(v => typeof v === 'function')) {
throw new Error('findOneAndDelete() is promise-only in Mongoose 7+');
}
return model.findOneAndDelete(filter, options);
} Type guard
const isLegacyCallback = (v) => typeof v === 'function';
Try / catch
try {
const doc = await Model.findOneAndDelete({ _id });
} catch (err) {
if (err?.message?.includes('no longer accepts a callback')) {
// fix the findOneAndDelete call site that still passes a callback
}
throw err;
} Prevention
- Await findOneAndDelete in token/session cleanup code
- Handle the null result for no match
- Upgrade session and auth middleware together with mongoose to avoid mixed styles
When it happens
Trigger: Model.findOneAndDelete({ _id }, (err, doc) => {...}); .findOneAndDelete(cb) with the callback in the filter slot; a function passed in the options slot.
Common situations: Session/token cleanup code and account-deletion routes written for Mongoose 6; upgrades to mongoose 7/8; old middleware chains that forward callbacks.
Related errors
- Query.prototype.deleteOne() no longer accepts a callback
- Query.prototype.deleteMany() no longer accepts a callback
- Model.findOneAndDelete() no longer accepts a callback
- Model.findByIdAndDelete() no longer accepts a callback
- Query.prototype.find() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/676ceef7d0ec2263.
Report an issue: GitHub.