mongodb/node-mongodb-native · error · MongoBatchReExecutionError
This batch has already been executed, create new batch to ex
Error message
This batch has already been executed, create new batch to execute
What it means
Thrown as MongoBatchReExecutionError when BulkOperationBase.execute() is called on a bulk operation that has already been executed (this.s.executed is true). A BulkOperationBase instance is single-use; once execute() runs, the internal batches are consumed and the instance cannot be reused.
Source
Thrown at src/bulk/common.ts:1183
get writeConcern(): WriteConcern | undefined {
return this.s.writeConcern;
}
get batches(): Batch[] {
const batches = [...this.s.batches];
if (this.isOrdered) {
if (this.s.currentBatch) batches.push(this.s.currentBatch);
} else {
if (this.s.currentInsertBatch) batches.push(this.s.currentInsertBatch);
if (this.s.currentUpdateBatch) batches.push(this.s.currentUpdateBatch);
if (this.s.currentRemoveBatch) batches.push(this.s.currentRemoveBatch);
}
return batches;
}
async execute(options: BulkWriteOptions = {}): Promise<BulkWriteResult> {
if (this.s.executed) {
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');View on GitHub (pinned to 3366c21a63)
Solutions
- Create a fresh bulk op via collection.initializeOrderedBulkOp() / initializeUnorderedBulkOp() before each execute().
- In retry logic, rebuild the operation list inside the retry block, not outside it.
- Use collection.bulkWrite(ops) for one-shot calls; the driver creates a new internal op each time.
Example fix
// before
const bulk = coll.initializeOrderedBulkOp();
bulk.find({_id:1}).updateOne({$set:{a:1}});
await bulk.execute();
await bulk.execute(); // throws
// after
async function run() {
const bulk = coll.initializeOrderedBulkOp();
bulk.find({_id:1}).updateOne({$set:{a:1}});
return bulk.execute();
} Defensive patterns
Strategy: validation
Validate before calling
function assertNotExecuted(bulk) {
if (bulk.s.executed) {
throw new Error('bulk op already executed; create a new one');
}
} Type guard
function isFreshBulkOp(bulk) {
return bulk != null && bulk.s != null && bulk.s.executed === false;
} Try / catch
try {
await bulk.execute();
} catch (e) {
if (e instanceof MongoBatchReExecutionError) {
// create a fresh bulk op and rebuild operations
}
} Prevention
- Never cache bulk op instances; create per use.
- Build the operation list inside any retry loop, not outside it.
- Prefer collection.bulkWrite(ops) for one-shot calls.
When it happens
Trigger: Calling await bulk.execute() twice on the same bulk op object. Holding a bulk op in a long-lived variable and calling execute() in a retry loop without creating a fresh instance.
Common situations: Retry logic that re-invokes execute() on failure; reusing a bulk op across request handlers; caching a bulk op instance.
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/4cfe6cd825475abf.json.
Report an issue: GitHub.