{"record":{"id":"4cfe6cd825475abf","repo":"mongodb/node-mongodb-native","slug":"this-batch-has-already-been-executed-create-new-b","errorCode":null,"errorMessage":"This batch has already been executed, create new batch to execute","messagePattern":"This batch has already been executed, create new batch to execute","errorType":"exception","errorClass":"MongoBatchReExecutionError","httpStatus":null,"severity":"error","filePath":"src/bulk/common.ts","lineNumber":1183,"sourceCode":"  get writeConcern(): WriteConcern | undefined {\n    return this.s.writeConcern;\n  }\n\n  get batches(): Batch[] {\n    const batches = [...this.s.batches];\n    if (this.isOrdered) {\n      if (this.s.currentBatch) batches.push(this.s.currentBatch);\n    } else {\n      if (this.s.currentInsertBatch) batches.push(this.s.currentInsertBatch);\n      if (this.s.currentUpdateBatch) batches.push(this.s.currentUpdateBatch);\n      if (this.s.currentRemoveBatch) batches.push(this.s.currentRemoveBatch);\n    }\n    return batches;\n  }\n\n  async execute(options: BulkWriteOptions = {}): Promise<BulkWriteResult> {\n    if (this.s.executed) {\n      throw new MongoBatchReExecutionError();\n    }\n\n    const writeConcern = WriteConcern.fromOptions(options);\n    if (writeConcern) {\n      this.s.writeConcern = writeConcern;\n    }\n\n    // If we have current batch\n    if (this.isOrdered) {\n      if (this.s.currentBatch) this.s.batches.push(this.s.currentBatch);\n    } else {\n      if (this.s.currentInsertBatch) this.s.batches.push(this.s.currentInsertBatch);\n      if (this.s.currentUpdateBatch) this.s.batches.push(this.s.currentUpdateBatch);\n      if (this.s.currentRemoveBatch) this.s.batches.push(this.s.currentRemoveBatch);\n    }\n    // If we have no operations in the bulk raise an error\n    if (this.s.batches.length === 0) {\n      throw new MongoInvalidArgumentError('Invalid BulkOperation, Batch cannot be empty');","sourceCodeStart":1165,"sourceCodeEnd":1201,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/bulk/common.ts#L1165-L1201","documentation":"Thrown as MongoBatchReExecutionError by BulkOperationBase.execute() (src/bulk/common.ts:1183) when execute() is called on a bulk operation that has already run. BulkOperationBase mutates internal state (s.executed = true) and consumes its batches during execution, so a second execution cannot rebuild the same batches; the driver forces you to create a new bulk operation instead.","triggerScenarios":"Calling `await bulk.execute()` twice on the same OrderedBulkOperation/UnorderedBulkOperation instance. The guard is `if (this.s.executed)` at src/bulk/common.ts:1182.","commonSituations":"Retrying an operation in a try/catch by re-running the same builder, calling execute() in a loop that reuses the bulk object, or a refactor that wraps execute() without recreating the bulk op.","solutions":["Create a fresh bulk operation for each execution: `const bulk = coll.initializeUnorderedBulkOp(); ... await bulk.execute();` — do not reuse `bulk`.","If you need to retry the same logical writes, rebuild the bulk op from the source data each attempt, or use collection.bulkWrite(...) which constructs a new bulk internally per call.","Audit retry logic to ensure it does not retain the bulk builder across attempts."],"exampleFix":"// before\nconst bulk = coll.initializeOrderedBulkOp();\nbulk.find({ _id: 1 }).updateOne({ $set: { a: 1 } });\nawait bulk.execute();\nawait bulk.execute(); // throws MongoBatchReExecutionError\n\n// after\nasync function runOnce() {\n  const bulk = coll.initializeOrderedBulkOp();\n  bulk.find({ _id: 1 }).updateOne({ $set: { a: 1 } });\n  return bulk.execute();\n}\nawait runOnce();\nawait runOnce();","handlingStrategy":"validation","validationCode":"let bulkExecuted = false;\nasync function executeOnce(bulk: OrderedBulkOperation | UnorderedBulkOperation) {\n  if (bulkExecuted) throw new Error('bulk already executed; build a new one');\n  bulkExecuted = true;\n  return bulk.execute();\n}\n\n// better: always construct a fresh bulk op per execution\nasync function runBulk(ops: (() => void)[]) {\n  const bulk = coll.initializeUnorderedBulkOp();\n  ops.forEach(fn => fn()); // rebuild\n  return bulk.execute();\n}","typeGuard":"// There is no exposed 'isExecuted' on the public type; track lifecycle externally.\n// Wrap the bulk op in a guard object:\nfunction onceBulk<T extends { execute: (...a: any[]) => Promise<any> }>(bulk: T) {\n  let done = false;\n  return {\n    bulk,\n    async execute(...args: Parameters<T['execute']>) {\n      if (done) throw new Error('bulk already executed; create a new one');\n      done = true;\n      return bulk.execute(...args);\n    }\n  };\n}","tryCatchPattern":"try {\n  await bulk.execute();\n} catch (e) {\n  if (e instanceof MongoBatchReExecutionError) {\n    // rebuild a new bulk op from source data instead of reusing\n    const fresh = coll.initializeOrderedBulkOp();\n    // ... re-add operations ...\n    await fresh.execute();\n  } else throw e;\n}","preventionTips":["Treat a bulk op as single-use: build, execute, discard.","In retry logic, rebuild the bulk op from the source data on each attempt; do not retain the builder.","Prefer collection.bulkWrite(ops) over the manual builder when retry is needed — it constructs a new bulk internally per call.","Track an 'executed' flag in any wrapper that exposes execute()."],"tags":["bulk-write","execute","state","lifecycle"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}