Automattic/mongoose · error · MongooseError

Cannot call `create()` with a session and multiple documents

Error message

Cannot call `create()` with a session and multiple documents unless `ordered: true` is set

What it means

Model.create() saves multiple documents in parallel with Promise.all by default. When a session is supplied, parallel saves can interleave on the same session (typically inside a transaction), so Mongoose requires ordered: true, which switches to a serial for-loop over $save() calls. If options.session is set, options.ordered is falsy, and more than one document is being created, this MongooseError is thrown (as a rejected promise, since create() is async).

Source

Thrown at lib/model.js:2746

        !this.schema.path('session')) {
      // Probably means the user is running into the common mistake of trying
      // to use a spread to specify options, see gh-7535
      utils.warn('WARNING: to pass a `session` to `Model.create()` in ' +
        'Mongoose, you **must** pass an array as the first argument. See: ' +
        'https://mongoosejs.com/docs/api/model.html#Model.create()');
    }
  }

  if (args.length === 0) {
    return Array.isArray(doc) ? [] : null;
  }
  let res = [];
  const immediateError = typeof options.aggregateErrors === 'boolean' ? !options.aggregateErrors : true;

  delete options.aggregateErrors; // dont pass on the option to "$save"

  if (options.session && !options.ordered && args.length > 1) {
    throw new MongooseError('Cannot call `create()` with a session and multiple documents unless `ordered: true` is set');
  }

  if (!Array.isArray(doc) && args.length === 1) {
    let toSave = doc;

    const Model = this.discriminators && doc[discriminatorKey] != null ?
      this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :
      this;
    if (Model == null) {
      throw new MongooseError(`Discriminator "${doc[discriminatorKey]}" not ` +
      `found for model "${this.modelName}"`);
    }

    if (!(toSave instanceof Model)) {
      toSave = new Model(toSave);
    }

    await toSave.$save(options);

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Add ordered: true: await Model.create([d1, d2], { session, ordered: true })
  2. Or create documents one at a time in the session: for (const d of docs) await Model.create(d, { session })
  3. Or use insertMany(docs, { session }) when middleware/hooks are not needed (insertMany is ordered by default)
  4. Only pass a session when one is actually required; plain create() calls without a session are unaffected

Example fix

// before
await session.withTransaction(async () => {
  await User.create([u1, u2], { session }); // throws
});

// after
await session.withTransaction(async () => {
  await User.create([u1, u2], { session, ordered: true });
});
Defensive patterns

Strategy: validation

Validate before calling

function createWithSession(Model, docs, session) {
  const opts = { session, ordered: true };
  if (opts.session && !opts.ordered && docs.length > 1) {
    throw new Error('pass ordered: true when using a session with multiple docs');
  }
  return Model.create(docs, opts);
}

Try / catch

try {
  await Model.create(docs, { session, ordered: true });
} catch (err) {
  if (/unless `ordered: true` is set/.test(err.message)) {
    await Model.create(docs, { session, ordered: true }); // retry with ordered
  } else throw err;
}

Prevention

When it happens

Trigger: await Model.create([d1, d2], { session }) inside a transaction (or with any session) without ordered: true. Also Model.create(d1, d2, { session }) spread form with a session in options.

Common situations: Wrapping multi-document creation in withTransaction(); adding { session } to existing bulk create calls during a refactor to transactions; passing a session from caller middleware to a generic create helper.

Related errors


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