Automattic/mongoose · error · MongooseError

Model.createCollection() no longer accepts a callback

Error message

Model.createCollection() no longer accepts a callback

What it means

Model.createCollection() explicitly creates the MongoDB collection (applying capped/timeseries/collation options) and is async-only; Mongoose 7 removed callbacks, so passing a function as either argument throws before any driver call is made. The returned promise resolves to the driver collection object.

Source

Thrown at lib/model.js:1224

 *
 * #### Example:
 *
 *     const userSchema = new Schema({ name: String })
 *     const User = mongoose.model('User', userSchema);
 *
 *     User.createCollection().then(function(collection) {
 *       console.log('Collection is created!');
 *     });
 *
 * @api public
 * @param {object} [options] see [MongoDB driver docs](https://mongodb.github.io/node-mongodb-native/7.0/classes/Db.html#createCollection)
 * @returns {Promise}
 */

Model.createCollection = async function createCollection(options) {
  _checkContext(this, 'createCollection');
  if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function') {
    throw new MongooseError('Model.createCollection() no longer accepts a callback');
  }

  const preFilter = buildMiddlewareFilter(options, 'pre');
  const postFilter = buildMiddlewareFilter(options, 'post');

  // Remove middleware option before passing to MongoDB
  if (options?.middleware != null) {
    options = { ...options };
    delete options.middleware;
  }

  [options] = await this.hooks.execPre('createCollection', this, [options], { filter: preFilter }).catch(err => {
    if (err instanceof Kareem.skipWrappedFunction) {
      return [err];
    }
    throw err;
  });

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Await the call: `const collection = await User.createCollection(opts);`
  2. Wrap setup in try/catch or .catch() for the error path (e.g. NamespaceExists)
  3. Grep for `createCollection\(` and ensure no trailing function argument remains

Example fix

// before
User.createCollection({ capped: true, size: 1024 }, (err) => { ... });

// after
await User.createCollection({ capped: true, size: 1024 });
Defensive patterns

Strategy: validation

Validate before calling

const isFn = (a) => typeof a === 'function';
if (isFn(options)) throw new TypeError('createCollection() is promise-only');
const collection = await User.createCollection(options);

Try / catch

try {
  await User.createCollection(opts);
} catch (err) {
  if (err?.code === 48 /* NamespaceExists */) return; // idempotent bootstrap
  throw err;
}

Prevention

When it happens

Trigger: `User.createCollection(opts, cb)` or `User.createCollection(cb)`; code copied from Mongoose 5/6 docs where callbacks were the default style.

Common situations: Post-migration leftovers from mongoose < 7; setup scripts that used callbacks for collection bootstrapping.

Related errors


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