mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Operation passed in cannot be an Array

Error message

Operation passed in cannot be an Array

What it means

Thrown by UnorderedBulkOperation.addToOperationsList() when the document argument is an array. Each call must receive a single document; list inputs must be iterated. Mirror of the ordered variant's guard.

Source

Thrown at src/bulk/unordered.ts:103

      // New batch if we exceed the max batch op size
      this.s.currentBatch.size + 1 >= this.s.maxWriteBatchSize ||
      // New batch if we exceed the maxBatchSizeBytes. Only matters if batch already has a doc,
      // since we can't sent an empty batch
      (this.s.currentBatch.size > 0 &&
        this.s.currentBatch.sizeBytes + maxKeySize + bsonSize >= this.s.maxBatchSizeBytes) ||
      // New batch if the new op does not have the same op type as the current batch
      this.s.currentBatch.batchType !== batchType
    ) {
      // Save the batch to the execution stack
      this.s.batches.push(this.s.currentBatch);

      // Create a new batch
      this.s.currentBatch = new Batch(batchType, this.s.currentIndex);
    }

    // We have an array of documents
    if (Array.isArray(document)) {
      throw new MongoInvalidArgumentError('Operation passed in cannot be an Array');
    }

    this.s.currentBatch.operations.push(document);
    if (buffer != null) this.s.currentBatch.serializedOperations.push(buffer);
    this.s.currentBatch.originalIndexes.push(this.s.currentIndex);
    this.s.currentIndex = this.s.currentIndex + 1;

    // Save back the current Batch to the right type
    if (batchType === BatchType.INSERT) {
      this.s.currentInsertBatch = this.s.currentBatch;
      this.s.bulkResult.insertedIds.push({
        index: this.s.bulkResult.insertedIds.length,
        _id: (document as Document)._id
      });
    } else if (batchType === BatchType.UPDATE) {
      this.s.currentUpdateBatch = this.s.currentBatch;
    } else if (batchType === BatchType.DELETE) {
      this.s.currentRemoveBatch = this.s.currentBatch;

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Call addToOperationsList once per document.
  2. Use collection.bulkWrite(ops) to let the driver iterate the list.

Example fix

// before
addToOperationsList(BatchType.INSERT, [docA, docB]);

// after
for (const doc of [docA, docB]) addToOperationsList(BatchType.INSERT, doc);
Defensive patterns

Strategy: type-guard

Validate before calling

function assertSingleDoc(doc) {
  if (Array.isArray(doc)) {
    throw new TypeError('addToOperationsList expects a single document, not an array');
  }
}

Type guard

function isSingleDocument(doc) {
  return doc != null && typeof doc === 'object' && !Array.isArray(doc);
}

Try / catch

try {
  addToOperationsList(batchType, doc);
} catch (e) {
  if (/cannot be an Array/.test(e.message)) {
    for (const d of doc) addToOperationsList(batchType, d);
  }
}

Prevention

When it happens

Trigger: Internally calling addToOperationsList(batchType, [...]) with an array. Custom subclasses or middleware that pass arrays.

Common situations: Internal API misuse; middleware that batches documents into a single call.

Related errors


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