{"id":"40a693d1128c836c","repo":"mongodb/node-mongodb-native","slug":"operation-passed-in-cannot-be-an-array-40a693","errorCode":null,"errorMessage":"Operation passed in cannot be an Array","messagePattern":"Operation passed in cannot be an Array","errorType":"validation","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/bulk/unordered.ts","lineNumber":103,"sourceCode":"      // New batch if we exceed the max batch op size\n      this.s.currentBatch.size + 1 >= this.s.maxWriteBatchSize ||\n      // New batch if we exceed the maxBatchSizeBytes. Only matters if batch already has a doc,\n      // since we can't sent an empty batch\n      (this.s.currentBatch.size > 0 &&\n        this.s.currentBatch.sizeBytes + maxKeySize + bsonSize >= this.s.maxBatchSizeBytes) ||\n      // New batch if the new op does not have the same op type as the current batch\n      this.s.currentBatch.batchType !== batchType\n    ) {\n      // Save the batch to the execution stack\n      this.s.batches.push(this.s.currentBatch);\n\n      // Create a new batch\n      this.s.currentBatch = new Batch(batchType, this.s.currentIndex);\n    }\n\n    // We have an array of documents\n    if (Array.isArray(document)) {\n      throw new MongoInvalidArgumentError('Operation passed in cannot be an Array');\n    }\n\n    this.s.currentBatch.operations.push(document);\n    if (buffer != null) this.s.currentBatch.serializedOperations.push(buffer);\n    this.s.currentBatch.originalIndexes.push(this.s.currentIndex);\n    this.s.currentIndex = this.s.currentIndex + 1;\n\n    // Save back the current Batch to the right type\n    if (batchType === BatchType.INSERT) {\n      this.s.currentInsertBatch = this.s.currentBatch;\n      this.s.bulkResult.insertedIds.push({\n        index: this.s.bulkResult.insertedIds.length,\n        _id: (document as Document)._id\n      });\n    } else if (batchType === BatchType.UPDATE) {\n      this.s.currentUpdateBatch = this.s.currentBatch;\n    } else if (batchType === BatchType.DELETE) {\n      this.s.currentRemoveBatch = this.s.currentBatch;","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/bulk/unordered.ts#L85-L121","documentation":"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.","triggerScenarios":"Internally calling addToOperationsList(batchType, [...]) with an array. Custom subclasses or middleware that pass arrays.","commonSituations":"Internal API misuse; middleware that batches documents into a single call.","solutions":["Call addToOperationsList once per document.","Use collection.bulkWrite(ops) to let the driver iterate the list."],"exampleFix":"// before\naddToOperationsList(BatchType.INSERT, [docA, docB]);\n\n// after\nfor (const doc of [docA, docB]) addToOperationsList(BatchType.INSERT, doc);","handlingStrategy":"type-guard","validationCode":"function assertSingleDoc(doc) {\n  if (Array.isArray(doc)) {\n    throw new TypeError('addToOperationsList expects a single document, not an array');\n  }\n}","typeGuard":"function isSingleDocument(doc) {\n  return doc != null && typeof doc === 'object' && !Array.isArray(doc);\n}","tryCatchPattern":"try {\n  addToOperationsList(batchType, doc);\n} catch (e) {\n  if (/cannot be an Array/.test(e.message)) {\n    for (const d of doc) addToOperationsList(batchType, d);\n  }\n}","preventionTips":["Always iterate lists and enqueue one document per call.","Prefer collection.bulkWrite(ops) over internal addToOperationsList."],"tags":["bulk-write","unordered","internal","argument-error"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}