mongodb/node-mongodb-native · error · MongoTransactionError

Cannot call abortTransaction after calling commitTransaction

Error message

Cannot call abortTransaction after calling commitTransaction

What it means

`abortTransaction` throws MongoTransactionError when the state is `TRANSACTION_COMMITTED` or `TRANSACTION_COMMITTED_EMPTY` — once commit has been attempted you cannot abort that transaction. The commit's outcome must be resolved (possibly retried), not overturned by an abort.

Solutions

  1. Only abort if the transaction is still in progress: `if (session.inTransaction()) await session.abortTransaction();`.
  2. Do not abort after commit has been called — handle commit failures via retry/error labels instead.
  3. Adopt `withTransaction` for commit/retry logic and reserve manual abort for the callback body.

Example fix

// before
try {
  session.startTransaction();
  await collection.insertOne(doc, { session });
  await session.commitTransaction();
} catch (err) {
  await session.abortTransaction(); // throws if commit already ran
  throw err;
}

// after
try {
  session.startTransaction();
  await collection.insertOne(doc, { session });
  await session.commitTransaction();
} catch (err) {
  if (session.inTransaction()) await session.abortTransaction();
  throw err;
}
Defensive patterns

Strategy: validation

Validate before calling

function safeAbort(session) {
  // abort is only valid while the transaction is still in progress
  if (session.inTransaction()) return session.abortTransaction();
}

Type guard

function canAbortTxn(session) {
  return session.inTransaction();
}

Prevention

When it happens

Trigger: `session.startTransaction(); ... await session.commitTransaction(); await session.abortTransaction();` — commonly a commit-then-catch that decides to abort after the commit already ran.

Common situations: A catch block that aborts without checking whether the try block already committed; retry loops that abort after a failed commit attempt; misordered cleanup in a wrapper.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/47b9cf2bc42873ec. Report an issue: GitHub.

Appendix: source

Thrown at src/sessions.ts:594

    if (this.transaction.state === TxnState.NO_TRANSACTION) {
      throw new MongoTransactionError('No transaction started');
    }

    if (this.transaction.state === TxnState.STARTING_TRANSACTION) {
      // the transaction was never started, we can safely exit here
      this.transaction.transition(TxnState.TRANSACTION_ABORTED);
      return;
    }

    if (this.transaction.state === TxnState.TRANSACTION_ABORTED) {
      throw new MongoTransactionError('Cannot call abortTransaction twice');
    }

    if (
      this.transaction.state === TxnState.TRANSACTION_COMMITTED ||
      this.transaction.state === TxnState.TRANSACTION_COMMITTED_EMPTY
    ) {
      throw new MongoTransactionError(
        'Cannot call abortTransaction after calling commitTransaction'
      );
    }

    const command: {
      abortTransaction: 1;
      writeConcern?: WriteConcernOptions;
      recoveryToken?: Document;
    } = { abortTransaction: 1 };

    const timeoutMS =
      typeof options?.timeoutMS === 'number'
        ? options.timeoutMS
        : this.timeoutContext?.csotEnabled()
          ? this.timeoutContext.timeoutMS // refresh timeoutMS for abort operation
          : typeof this.timeoutMS === 'number'
            ? this.timeoutMS
            : null;

View on GitHub (pinned to dce7939f86)