{"record":{"id":"b38be4889dc60d0f","repo":"Automattic/mongoose","slug":"model-findoneanddelete-no-longer-accepts-a-callb","errorCode":null,"errorMessage":"Model.findOneAndDelete() no longer accepts a callback","messagePattern":"Model\\.findOneAndDelete\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":2564,"sourceCode":" * @param {object} conditions\n * @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())\n * @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)\n * @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())\n * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).\n * @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\n * @param {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.\n * @param {object|string} [options.select] sets the document fields to return.\n * @param {number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0\n * @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.\n * @return {Query}\n * @api public\n */\n\nModel.findOneAndDelete = function(conditions, options) {\n  _checkContext(this, 'findOneAndDelete');\n\n  if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {\n    throw new MongooseError('Model.findOneAndDelete() no longer accepts a callback');\n  }\n\n  let fields;\n  if (options) {\n    fields = options.select;\n    options.select = undefined;\n  }\n\n  const mq = new this.Query({}, {}, this, this.$__collection);\n  mq.select(fields);\n\n  return mq.findOneAndDelete(conditions, options);\n};\n\n/**\n * Issue a MongoDB `findOneAndDelete()` command by a document's _id field.\n * In other words, `findByIdAndDelete(id)` is a shorthand for\n * `findOneAndDelete({ _id: id })`.","sourceCodeStart":2546,"sourceCodeEnd":2582,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L2546-L2582","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nUser.findOneAndDelete({ email }, (err, doc) => { ... });\n\n// after\ntry {\n  const doc = await User.findOneAndDelete({ email });\n} catch (err) { ... }","handlingStrategy":"validation","validationCode":"function assertNoCallbacks(fnName, args) {\n  const i = args.findIndex(a => typeof a === 'function');\n  if (i !== -1) throw new TypeError(`${fnName}: callbacks removed in Mongoose 7; use await`);\n}\n// assertNoCallbacks('findOneAndDelete', [filter, options]);","typeGuard":null,"tryCatchPattern":"try {\n  const doc = await Model.findOneAndDelete(filter);\n} catch (err) {\n  if (/no longer accepts a callback/.test(err.message)) { /* legacy call site: migrate to await */ }\n  else throw err;\n}","preventionTips":["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"],"tags":["mongoose","callback","promise","migration","api-change","delete"],"backgroundTag":"callback-to-promise-migration","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}