mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Invalid BulkOperation, Batch cannot be empty
Error message
Invalid BulkOperation, Batch cannot be empty
What it means
Thrown by BulkOperationBase.execute() when no operations were ever added (this.s.batches is empty). Calling execute() on a bulk op where find()/insert()/raw() were never invoked is a programming error; the server would reject an empty batch anyway.
Source
Thrown at src/bulk/common.ts:1201
throw new MongoBatchReExecutionError();
}
const writeConcern = WriteConcern.fromOptions(options);
if (writeConcern) {
this.s.writeConcern = writeConcern;
}
// If we have current batch
if (this.isOrdered) {
if (this.s.currentBatch) this.s.batches.push(this.s.currentBatch);
} else {
if (this.s.currentInsertBatch) this.s.batches.push(this.s.currentInsertBatch);
if (this.s.currentUpdateBatch) this.s.batches.push(this.s.currentUpdateBatch);
if (this.s.currentRemoveBatch) this.s.batches.push(this.s.currentRemoveBatch);
}
// If we have no operations in the bulk raise an error
if (this.s.batches.length === 0) {
throw new MongoInvalidArgumentError('Invalid BulkOperation, Batch cannot be empty');
}
this.s.executed = true;
const finalOptions = resolveOptions(this.collection, { ...this.s.options, ...options });
// if there is no timeoutContext provided, create a timeoutContext and use it for
// all batches in the bulk operation
finalOptions.timeoutContext ??= TimeoutContext.create({
session: finalOptions.session,
timeoutMS: finalOptions.timeoutMS,
serverSelectionTimeoutMS: this.collection.client.s.options.serverSelectionTimeoutMS,
waitQueueTimeoutMS: this.collection.client.s.options.waitQueueTimeoutMS
});
if (finalOptions.session == null) {
// if there is not an explicit session provided to `execute()`, create
// an implicit session and use that for all batches in the bulk operation
return await this.collection.client.withSession({ explicit: false }, async session => {View on GitHub (pinned to 3366c21a63)
Solutions
- Guard execute() with a check: if (bulk.length === 0) return; before calling execute().
- Validate the input list is non-empty before initializing the bulk op.
- Use collection.bulkWrite(ops) and short-circuit when ops.length === 0.
Example fix
// before const bulk = coll.initializeUnorderedBulkOp(); for (const op of ops) bulk.raw(op); // ops is [] await bulk.execute(); // throws // after if (ops.length === 0) return; const bulk = coll.initializeUnorderedBulkOp(); for (const op of ops) bulk.raw(op); await bulk.execute();
Defensive patterns
Strategy: validation
Validate before calling
function executeIfNonEmpty(bulk) {
if (bulk.length === 0) return null;
return bulk.execute();
} Type guard
function bulkHasOps(bulk) {
return bulk != null && typeof bulk.length === 'number' && bulk.length > 0;
} Try / catch
try {
await bulk.execute();
} catch (e) {
if (e instanceof MongoInvalidArgumentError && /Batch cannot be empty/.test(e.message)) {
return; // nothing to do
}
throw e;
} Prevention
- Short-circuit when the input list is empty before initializing a bulk op.
- Check bulk.length before execute().
- Prefer collection.bulkWrite(ops) and guard with if (ops.length === 0) return.
When it happens
Trigger: Calling await bulk.execute() on a freshly initialized bulk op without adding any operations. Building operations conditionally such that none are added for an empty input list.
Common situations: Empty input arrays processed in a loop that adds zero ops; early-return logic that skips all op additions but still reaches execute(); tests that scaffold a bulk op but never populate it.
Related errors
- Update document requires atomic operators
- Replacement document must not use atomic operators
- Bulk find operation must specify a selector
- Operation must be an object with an operation key
- Raw operations are not allowed
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/5a6d951a644e7d7e.json.
Report an issue: GitHub.