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

  1. Use await: const res = await Model.bulkWrite(ops, { ordered: false }); inside try/catch
  2. Or .then()/.catch() on the returned promise
  3. Include bulkWrite in the Mongoose 7 callback-migration sweep alongside create/insertMany/find* methods
  4. Pin mongoose@6 temporarily if the rewrite must be deferred
  5. 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

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


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/c6160f29baf87f98. Report an issue: GitHub.