mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Argument "operations" must be an array of documents

Error message

Argument "operations" must be an array of documents

What it means

Thrown by Collection.bulkWrite() when the operations argument is not an Array. Each element must be one of the recognized bulk operation shapes (insertOne, updateOne, updateMany, replaceOne, deleteOne, deleteMany). This MongoInvalidArgumentError is raised before the bulk op is built or any connection is checked out.

Source

Thrown at src/collection.ts:367

   * - `updateOne`
   * - `updateMany`
   * - `deleteOne`
   * - `deleteMany`
   *
   * If documents passed in do not contain the **_id** field,
   * one will be added to each of the documents missing it by the driver, mutating the document. This behavior
   * can be overridden by setting the **forceServerObjectId** flag.
   *
   * @param operations - Bulk operations to perform
   * @param options - Optional settings for the command
   * @throws MongoDriverError if operations is not an array
   */
  async bulkWrite(
    operations: ReadonlyArray<AnyBulkWriteOperation<TSchema>>,
    options?: BulkWriteOptions
  ): Promise<BulkWriteResult> {
    if (!Array.isArray(operations)) {
      throw new MongoInvalidArgumentError('Argument "operations" must be an array of documents');
    }

    options = resolveOptions(this, options ?? {});

    // TODO(NODE-7071): remove once the client doesn't need to be connected to construct
    // bulk operations
    const isConnected = this.client.topology != null;
    if (!isConnected) {
      await autoConnect(this.client);
    }

    // Create the bulk operation
    const bulk: BulkOperationBase =
      options.ordered === false
        ? this.initializeUnorderedBulkOp(options)
        : this.initializeOrderedBulkOp(options);

    // for each op go through and add to the bulk

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Ensure the argument is always an array: ops = ops ?? []; at the call site.
  2. Wrap a single operation: bulkWrite(Array.isArray(ops) ? ops : [ops]).
  3. Guard with Array.isArray(ops) and throw a domain-specific error before calling.
  4. Type the producer function's return as AnyBulkWriteOperation<T>[] to catch regressions.

Example fix

// before
const ops = condition ? [{ updateOne: {...} }] : undefined;
await collection.bulkWrite(ops);
// after
const ops = condition ? [{ updateOne: {...} }] : [];
await collection.bulkWrite(ops);
Defensive patterns

Strategy: type-guard

Validate before calling

function asBulkOps<T>(ops: unknown): T[] {
  if (!Array.isArray(ops)) {
    throw new TypeError('bulkWrite requires an array of operations');
  }
  return ops as T[];
}
await collection.bulkWrite(asBulkOps(operations));

Type guard

const isBulkOperationArray = (v: unknown): v is object[] =>
  Array.isArray(v) && v.every(o => o != null && typeof o === 'object');

Try / catch

try {
  await collection.bulkWrite(operations);
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /operations.*must be an array/.test(e.message)) {
    throw new TypeError('Expected an array of bulk operations');
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a single operation object instead of an array; passing undefined; passing a generator or custom iterable that is not an Array; passing an array-like object ({length, 0, 1}) that fails Array.isArray.

Common situations: Building operations conditionally and forgetting to initialize the accumulator to []; spreading a possibly-undefined value; refactoring from a fluent bulk to bulkWrite without wrapping; JSON input parsed into an object rather than an array.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/982206892efff534.json. Report an issue: GitHub.