{"id":"47b9cf2bc42873ec","repo":"mongodb/node-mongodb-native","slug":"cannot-call-aborttransaction-after-calling-committ","errorCode":null,"errorMessage":"Cannot call abortTransaction after calling commitTransaction","messagePattern":"Cannot call abortTransaction after calling commitTransaction","errorType":"exception","errorClass":"MongoTransactionError","httpStatus":null,"severity":"error","filePath":"src/sessions.ts","lineNumber":594,"sourceCode":"    if (this.transaction.state === TxnState.NO_TRANSACTION) {\n      throw new MongoTransactionError('No transaction started');\n    }\n\n    if (this.transaction.state === TxnState.STARTING_TRANSACTION) {\n      // the transaction was never started, we can safely exit here\n      this.transaction.transition(TxnState.TRANSACTION_ABORTED);\n      return;\n    }\n\n    if (this.transaction.state === TxnState.TRANSACTION_ABORTED) {\n      throw new MongoTransactionError('Cannot call abortTransaction twice');\n    }\n\n    if (\n      this.transaction.state === TxnState.TRANSACTION_COMMITTED ||\n      this.transaction.state === TxnState.TRANSACTION_COMMITTED_EMPTY\n    ) {\n      throw new MongoTransactionError(\n        'Cannot call abortTransaction after calling commitTransaction'\n      );\n    }\n\n    const command: {\n      abortTransaction: 1;\n      writeConcern?: WriteConcernOptions;\n      recoveryToken?: Document;\n    } = { abortTransaction: 1 };\n\n    const timeoutMS =\n      typeof options?.timeoutMS === 'number'\n        ? options.timeoutMS\n        : this.timeoutContext?.csotEnabled()\n          ? this.timeoutContext.timeoutMS // refresh timeoutMS for abort operation\n          : typeof this.timeoutMS === 'number'\n            ? this.timeoutMS\n            : null;","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/sessions.ts#L576-L612","documentation":"Thrown by ClientSession.abortTransaction() when the transaction state is TRANSACTION_COMMITTED or TRANSACTION_COMMITTED_EMPTY. Once committed, a transaction cannot be rolled back; the spec forbids this transition. It is a MongoTransactionError.","triggerScenarios":"A finally block calls abortTransaction() after commitTransaction() has already succeeded; re-aborting after a commit attempt.","commonSituations":"try { ...; await commit; } finally { await abort; } - the finally aborts a committed transaction; success path commits, then cleanup aborts.","solutions":["Only abort on the error path and only when still active: if (session.inTransaction()) await session.abortTransaction().","Do not put abortTransaction in a finally that also runs after a successful commit; keep abort strictly in catch.","Use withTransaction() so commit/abort sequencing is handled by the driver."],"exampleFix":"// before\ntry {\n  session.startTransaction();\n  await coll.insertOne(doc, { session });\n  await session.commitTransaction();\n} finally {\n  await session.abortTransaction(); // throws: already committed\n}\n\n// after\ntry {\n  session.startTransaction();\n  await coll.insertOne(doc, { session });\n  await session.commitTransaction();\n} catch (e) {\n  if (session.inTransaction()) await session.abortTransaction();\n  throw e;\n}","handlingStrategy":"validation","validationCode":"// abort only on error, only if still active\nif (session.inTransaction()) {\n  await session.abortTransaction();\n}","typeGuard":"function isAbortable(session: ClientSession): boolean {\n  return session.transaction.isActive;\n}","tryCatchPattern":"try {\n  await session.abortTransaction();\n} catch (e) {\n  if (e instanceof MongoTransactionError && /after calling commitTransaction/.test(e.message)) {\n    // committed; cannot abort, ignore\n  } else throw e;\n}","preventionTips":["Keep abortTransaction strictly in the catch path, never in finally after commit.","Gate abort with session.inTransaction() which is false after commit.","Use withTransaction() to avoid manual abort entirely."],"tags":["sessions","transactions","state-machine","control-flow"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}