MongoServerError: Transaction number 1 on session 0x1234 is not the expected transaction number (expected 2)
ID: mongodb/transaction-number-mismatch
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| MongoDB 4.2 | active | — | — | — |
| MongoDB 5.0 | active | — | — | — |
| MongoDB 6.0 | active | — | — | — |
| MongoDB 7.0 | active | — | — | — |
Root Cause
A client attempted to commit or abort a transaction with a stale transaction number, likely due to a retry logic bug where the same session is reused without incrementing the transaction number, or a session is accidentally shared across concurrent transactions.
generic中文
客户端尝试使用过时的事务编号提交或中止事务,可能是由于重试逻辑错误,同一会话被重用而未递增事务编号,或会话被意外地在并发事务间共享。
Official Documentation
https://www.mongodb.com/docs/manual/core/transactions/Workarounds
-
90% success Ensure each transaction uses a new session or explicitly increments the transaction number. In Node.js driver: use `session.startTransaction()` and `session.commitTransaction()` within a loop that creates a new session for each attempt. Example: `const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }`
Ensure each transaction uses a new session or explicitly increments the transaction number. In Node.js driver: use `session.startTransaction()` and `session.commitTransaction()` within a loop that creates a new session for each attempt. Example: `const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }` -
88% success For retry logic, use a fresh session for each retry attempt instead of reusing the same session. In Python: `with client.start_session() as session: session.start_transaction(); ...` inside the retry loop.
For retry logic, use a fresh session for each retry attempt instead of reusing the same session. In Python: `with client.start_session() as session: session.start_transaction(); ...` inside the retry loop.
-
85% success Check for accidental session sharing in async code (e.g., passing the same session object to multiple concurrent coroutines). Use `session.advanceTransactionNumber()` if driver supports it, or enforce sequential transaction processing per session.
Check for accidental session sharing in async code (e.g., passing the same session object to multiple concurrent coroutines). Use `session.advanceTransactionNumber()` if driver supports it, or enforce sequential transaction processing per session.
中文步骤
确保每个事务使用新会话或显式递增事务编号。在 Node.js 驱动中:在每次尝试的循环中使用 `session.startTransaction()` 和 `session.commitTransaction()` 创建新会话。示例:`const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }`对于重试逻辑,每次重试尝试使用新会话,而不是重用同一会话。在 Python 中:在重试循环内使用 `with client.start_session() as session: session.start_transaction(); ...`。
检查异步代码中的意外会话共享(例如,将同一会话对象传递给多个并发协程)。如果驱动程序支持,使用 `session.advanceTransactionNumber()`,或强制每个会话按顺序处理事务。
Dead Ends
Common approaches that don't work:
-
90% fail
The underlying session management bug in the code remains; the error will recur on the next transaction.
-
85% fail
Killing the session only frees server resources; the client code still holds a stale session reference and will create a new session with the same problem.
-
95% fail
The error is about transaction number sequencing, not timeout; changing timeouts has no effect.