Automattic/mongoose · error · MongooseError
Model.bulkWrite() no longer accepts a callback
Error message
Model.bulkWrite() no longer accepts a callback
What it means
Model.bulkWrite() is async and promise-only in Mongoose 7+; the guard throws (as a rejected promise) when options is a function or a third argument is a function, covering legacy bulkWrite(ops, callback) and bulkWrite(ops, options, callback) call forms.
Source
Thrown at lib/model.js:3426
* @param {number} [options.wtimeout=null] The [write concern timeout](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout).
* @param {boolean} [options.j=true] If false, disable [journal acknowledgement](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option)
* @param {boolean} [options.skipValidation=false] Set to true to skip Mongoose schema validation on bulk write operations. Mongoose currently runs validation on `insertOne` and `replaceOne` operations by default.
* @param {boolean} [options.bypassDocumentValidation=false] If true, disable [MongoDB server-side schema validation](https://www.mongodb.com/docs/manual/core/schema-validation/) for all writes in this bulk.
* @param {boolean} [options.throwOnValidationError=false] If true and `ordered: false`, throw an error if one of the operations failed validation, but all valid operations completed successfully. Note that Mongoose will still send all valid operations to the MongoDB server.
* @param {boolean|"throw"} [options.strict=null] Overwrites the [`strict` option](https://mongoosejs.com/docs/guide.html#strict) on schema. If false, allows filtering and writing fields not defined in the schema for all writes in this bulk.
* @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware
* @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks
* @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks
* @return {Promise} resolves to a [`BulkWriteOpResult`](https://mongodb.github.io/node-mongodb-native/7.0/classes/BulkWriteResult.html) if the operation succeeds
* @api public
*/
Model.bulkWrite = async function bulkWrite(ops, options) {
_checkContext(this, 'bulkWrite');
if (typeof options === 'function' ||
typeof arguments[2] === 'function') {
throw new MongooseError('Model.bulkWrite() no longer accepts a callback');
}
const ThisModel = this;
return traceBulkWrite(function maybeTracedBulkWrite() { return _bulkWrite.call(ThisModel, ops, options); }, () => ({
operation: 'bulkWrite',
collection: ThisModel.collection.name,
database: ThisModel.db?.name,
serverAddress: ThisModel.db?.host,
serverPort: ThisModel.db?.port,
args: { ops, options }
}));
};
async function _bulkWrite(ops, options) {
options = options || {};
const preFilter = buildMiddlewareFilter(options, 'pre');
const postFilter = buildMiddlewareFilter(options, 'post');
View on GitHub (pinned to 49cdab0136)
Solutions
- Use await: const res = await Model.bulkWrite(ops, { ordered: false }); inside try/catch
- Or .then()/.catch() on the returned promise
- Include bulkWrite in the Mongoose 7 callback-migration sweep alongside create/insertMany/find* methods
- Pin mongoose@6 temporarily if the rewrite must be deferred
- Use TypeScript to catch removed overloads at compile time
Example fix
// before
User.bulkWrite(ops, (err, res) => { ... });
// after
const res = await User.bulkWrite(ops); Defensive patterns
Strategy: validation
Validate before calling
function bulkWriteSafe(Model, ops, options) {
if (typeof options === 'function') throw new TypeError('bulkWrite: use await, not a callback');
return Model.bulkWrite(ops, options);
} Try / catch
try {
const res = await Model.bulkWrite(ops, { ordered: false });
} catch (err) {
if (/no longer accepts a callback/.test(err.message)) { /* migrate call site to await */ }
else throw err;
} Prevention
- Migrate bulkWrite call sites with the same sweep as insertMany/create
- TypeScript catches removed callback overloads
- Keep bulk operation helpers promise-based and centralized
When it happens
Trigger: Model.bulkWrite(ops, cb) with the callback in the options slot, or Model.bulkWrite(ops, { ordered: false }, cb) with the callback third.
Common situations: Migrating bulk-migration scripts from Mongoose 6; wrapper utilities that append callbacks; copy-pasted legacy snippets performing bulk updates.
Related errors
- Model.insertMany() no longer accepts a callback
- Model.findByIdAndUpdate() no longer accepts a callback
- Model.findOneAndDelete() no longer accepts a callback
- Model.findByIdAndDelete() no longer accepts a callback
- Model.findOneAndReplace() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/c6160f29baf87f98.
Report an issue: GitHub.