Automattic/mongoose · error · MongooseError
Model.findOneAndDelete() no longer accepts a callback
Error message
Model.findOneAndDelete() no longer accepts a callback
What it means
Mongoose 7 removed callback support from all Model and Query APIs; findOneAndDelete() returns a Query (thenable) only. The function throws this MongooseError synchronously when arguments[0], arguments[1], or arguments[2] is a function, covering a callback passed as conditions, options, or the trailing third argument.
Source
Thrown at lib/model.js:2564
* @param {object} conditions
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {object|string|string[]} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
* @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 {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {object|string} [options.select] sets the document fields to return.
* @param {number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
* @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}
* @api public
*/
Model.findOneAndDelete = function(conditions, options) {
_checkContext(this, 'findOneAndDelete');
if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {
throw new MongooseError('Model.findOneAndDelete() no longer accepts a callback');
}
let fields;
if (options) {
fields = options.select;
options.select = undefined;
}
const mq = new this.Query({}, {}, this, this.$__collection);
mq.select(fields);
return mq.findOneAndDelete(conditions, options);
};
/**
* Issue a MongoDB `findOneAndDelete()` command by a document's _id field.
* In other words, `findByIdAndDelete(id)` is a shorthand for
* `findOneAndDelete({ _id: id })`.View on GitHub (pinned to 49cdab0136)
Solutions
- Replace the callback with await: const doc = await Model.findOneAndDelete(filter); inside try/catch
- Or use .then()/.catch() on the returned Query
- During upgrade, grep for findOneAndDelete call sites passing functions and migrate them together with all other callback-based Model methods (findOneAndUpdate, findByIdAndDelete, create, etc.)
- Pin mongoose@6 temporarily if the migration cannot be completed now
- Use TypeScript so the removed callback overloads are caught at compile time
Example fix
// before
User.findOneAndDelete({ email }, (err, doc) => { ... });
// after
try {
const doc = await User.findOneAndDelete({ email });
} catch (err) { ... } Defensive patterns
Strategy: validation
Validate before calling
function assertNoCallbacks(fnName, args) {
const i = args.findIndex(a => typeof a === 'function');
if (i !== -1) throw new TypeError(`${fnName}: callbacks removed in Mongoose 7; use await`);
}
// assertNoCallbacks('findOneAndDelete', [filter, options]); Try / catch
try {
const doc = await Model.findOneAndDelete(filter);
} catch (err) {
if (/no longer accepts a callback/.test(err.message)) { /* legacy call site: migrate to await */ }
else throw err;
} Prevention
- Migrate delete call sites together with the rest of the Mongoose 7 sweep; do not leave mixed styles
- Enable TypeScript so removed callback overloads fail to compile
- Search tests too: helper functions appending mocha done() to Mongoose calls trigger this
When it happens
Trigger: Calling Model.findOneAndDelete(filter, options, callback) or Model.findOneAndDelete(filter, callback) with legacy callback-style code. Also fires when a function value accidentally lands in the filter or options position due to argument-order mistakes.
Common situations: Migrating a codebase from Mongoose 6 to 7/8 with untouched delete call sites; old tutorials using (err, doc) => {} handlers; helper libraries built against the pre-7 API.
Related errors
- Model.findByIdAndDelete() no longer accepts a callback
- Model.findByIdAndUpdate() no longer accepts a callback
- Model.findOneAndReplace() no longer accepts a callback
- Model.create() 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/b38be4889dc60d0f.
Report an issue: GitHub.