{"record":{"id":"6f467b7328e6dcc7","repo":"Automattic/mongoose","slug":"query-prototype-deletemany-no-longer-accepts-a-c","errorCode":null,"errorMessage":"Query.prototype.deleteMany() no longer accepts a callback","messagePattern":"Query\\.prototype\\.deleteMany\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/query.js","lineNumber":3323,"sourceCode":" *\n * #### Example:\n *\n *     const res = await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });\n *     // `0` if no docs matched the filter, number of docs deleted otherwise\n *     res.deletedCount;\n *\n * @param {object|Query} [filter] mongodb selector\n * @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())\n * @param {boolean} [options.requireFilter=false] If true, throws an error if the filter is empty (`{}`)\n * @return {Query} this\n * @see DeleteResult https://mongodb.github.io/node-mongodb-native/7.0/interfaces/DeleteResult.html\n * @see deleteMany https://mongodb.github.io/node-mongodb-native/7.0/classes/Collection.html#deleteMany\n * @api public\n */\n\nQuery.prototype.deleteMany = function(filter, options) {\n  if (typeof filter === 'function' || typeof options === 'function' || typeof arguments[2] === 'function') {\n    throw new MongooseError('Query.prototype.deleteMany() no longer accepts a callback');\n  }\n  this.setOptions(options);\n  this.op = 'deleteMany';\n\n  if (canMerge(filter)) {\n    this.merge(filter);\n\n    prepareDiscriminatorCriteria(this);\n  } else if (filter != null) {\n    this.error(new ObjectParameterError(filter, 'filter', 'deleteMany'));\n  }\n\n  return this;\n};\n\n/**\n * Execute a `deleteMany()` query\n *","sourceCodeStart":3305,"sourceCodeEnd":3341,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/query.js#L3305-L3341","documentation":"Query.prototype.deleteMany(filter, options) throws when filter, options, or a third positional argument is a function, mirroring the Mongoose 7 callback removal across all query helpers. The error is thrown while building the query, so bulk-delete cron jobs and scripts from the callback era fail on their first call after upgrading.","triggerScenarios":"Model.deleteMany({ stale: true }, (err) => {...}); .deleteMany(cb); a function in the options slot.","commonSituations":"Scheduled cleanup jobs and TTL sweepers written for Mongoose 6; upgrades to mongoose 7/8; batch-admin endpoints.","solutions":["Use await: const result = await Model.deleteMany({ stale: true })","Read result.deletedCount for the number removed","Sweep for deleteMany( calls with callbacks during the migration"],"exampleFix":"// before\nModel.deleteMany({ stale: true }, (err, res) => {\n  if (err) return next(err);\n  res.json({ removed: res.deletedCount });\n});\n\n// after\ntry {\n  const result = await Model.deleteMany({ stale: true });\n  res.json({ removed: result.deletedCount });\n} catch (err) {\n  next(err);\n}","handlingStrategy":"validation","validationCode":"function deleteManySafe(model, filter, options) {\n  if ([filter, options].some(v => typeof v === 'function')) {\n    throw new Error('deleteMany() is promise-only in Mongoose 7+');\n  }\n  return model.deleteMany(filter, options);\n}","typeGuard":"const isLegacyCallback = (v) => typeof v === 'function';","tryCatchPattern":"try {\n  const result = await Model.deleteMany({ stale: true });\n} catch (err) {\n  if (err?.message?.includes('no longer accepts a callback')) {\n    // fix the deleteMany call site that still passes a callback\n  }\n  throw err;\n}","preventionTips":["Rewrite cron/cleanup scripts to awaited deleteMany calls before upgrading","Prefer explicit filters; Mongoose also warns on empty filters for deletes","Smoke-test scheduled jobs after a mongoose major upgrade"],"tags":["mongoose","callback","promise","migration","breaking-change","delete"],"backgroundTag":"legacy-callback-removed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}