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 as MongoInvalidArgumentError by OrderedBulkOperation.addToOperationsList() (src/bulk/ordered.ts:88) when the document passed to addToOperationsList is a JavaScript Array. addToOperationsList expects a single BSON document (or update/delete statement); passing an array is a structural mistake because the bulk op processes one op at a time and has already serialized the value as if it were a document.
Solutions
- Ensure the value passed for a single op is a plain object, not an array — iterate and add each element as its own operation if you have many.
- If you have an array of documents to insert, call bulk.insert(doc) per element rather than bulk.insert(docArray).
- Audit any custom wrapper that forwards payloads into addToOperationsList to confirm it passes documents one at a time.
Example fix
// before: passing an array where a single document is expected
for (const doc of docs) {
// some custom path ends up calling addToOperationsList(BatchType.INSERT, docs)
}
// after: add each document individually
for (const doc of docs) {
bulk.insert(doc); // one document per call
} Defensive patterns
Strategy: type-guard
Validate before calling
function isSingleDocument(doc: unknown): boolean {
return doc != null && typeof doc === 'object' && !Array.isArray(doc);
}
for (const op of ops) {
const doc = (op as any).insertOne?.document;
if (doc != null && !isSingleDocument(doc)) {
throw new Error('expected a single document, got an array');
}
} Type guard
function isSingleDocument(doc: unknown): doc is Record<string, unknown> {
return doc != null && typeof doc === 'object' && !Array.isArray(doc);
} Try / catch
try {
await bulk.execute();
} catch (e) {
if (e instanceof MongoInvalidArgumentError && /cannot be an Array/.test(e.message)) {
// flatten any array-valued document into one insert per element, then re-execute
} else throw e;
} Prevention
- Pass one document per insert/update/delete call; iterate arrays externally.
- Type document parameters as Record<string, unknown>, not as unknown[] or any[].
- Validate at API boundaries that payloads are not arrays.
- Audit custom driver wrappers to ensure they forward single documents.
When it happens
Trigger: An internal/builder caller (or a user reaching addToOperationsList via raw() with a malformed insert) passes an Array where a Document is expected. Guarded by `if (Array.isArray(document))` at src/bulk/ordered.ts:87.
Common situations: Mostly an internal-driver or advanced-usage error; can surface if a user constructs an operation whose `document`/`update`/`replacement` field is an array where the API expects a single object, or when wrapping the driver in a custom layer that forwards arrays. Very rare through the standard bulkWrite() path.
Related errors
- Document is larger than the maximum size
- Argument "operations" must be an array of documents
- Bulk find operation must specify a selector
- bulkWrite only supports insertOne, updateOne, updateMany…
- Document is larger than the maximum size
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/1b398d0afa50f732.
Report an issue: GitHub.
Appendix: source
Thrown at src/bulk/ordered.ts:88
// Create a new batch
this.s.currentBatch = new Batch(batchType, this.s.currentIndex);
// Reset the current size trackers
this.s.currentBatchSize = 0;
this.s.currentBatchSizeBytes = 0;
}
if (batchType === BatchType.INSERT) {
this.s.bulkResult.insertedIds.push({
index: this.s.currentIndex,
_id: (document as Document)._id
});
}
// We have an array of documents
if (Array.isArray(document)) {
throw new MongoInvalidArgumentError('Operation passed in cannot be an Array');
}
this.s.currentBatch.originalIndexes.push(this.s.currentIndex);
this.s.currentBatch.operations.push(document);
if (buffer != null) this.s.currentBatch.serializedOperations.push(buffer);
this.s.currentBatchSize += 1;
this.s.currentBatchSizeBytes += maxKeySize + bsonSize;
this.s.currentIndex += 1;
return this;
}
}
View on GitHub (pinned to dce7939f86)