stride3d/stride · error · TransactionException
The transaction being completed is not that last created…
Error message
The transaction being completed is not that last created transaction.
What it means
EndTransaction verifies that the transaction being completed is the one on top of the transactionsInProgress stack (LIFO order). This error is thrown when the passed transaction does not match the top of the stack, i.e. an inner transaction is still open or the wrong transaction reference was supplied.
Solutions
- Always close transactions in reverse creation order (LIFO): end the innermost transaction first.
- Audit nested CreateTransaction/EndTransaction pairs to guarantee strict nesting.
- Ensure no inner transaction is leaked when exceptions occur (use try/finally inside each scope).
- Verify you pass the same transaction instance returned by the most recent CreateTransaction/PushTransaction.
Example fix
// before stack.EndTransaction(outerTx); // innerTx still open // after stack.EndTransaction(innerTx); // close innermost first stack.EndTransaction(outerTx);
Defensive patterns
Strategy: validation
Validate before calling
// ensure LIFO order: only end the innermost transaction
if (transactionStack.TransactionInProgress && transaction == innermostOpenTransaction)
transactionStack.EndTransaction(transaction); Type guard
bool IsInnermost(Transaction transaction, Transaction innermost) => ReferenceEquals(transaction, innermost);
Try / catch
try
{
transactionStack.EndTransaction(transaction);
}
catch (TransactionException ex) when (ex.Message.Contains("not that last created transaction"))
{
// find and close the leaked inner transaction first
} Prevention
- Close transactions strictly in reverse creation order.
- Wrap each nested scope in try/finally to avoid leaked inner transactions.
- Never cache transaction objects for later out-of-order completion.
When it happens
Trigger: Calling EndTransaction(outerTransaction) while an inner nested transaction (created later) is still open; completing transactions out of creation order; passing a transaction from a different TransactionStack instance.
Common situations: Nested transaction scoping closed in the wrong order (crossing begin/end pairs); leaked inner transactions on exception paths; caching transaction objects and completing them later out of order.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- There is no transaction in progress in the transaction…
- There is not transaction in progress in the transaction…
- Unable to clear. A rollback or rollforward operation is in…
- Unable to rollback. A rollback or rollforward operation is…
- Unable to rollback. A transaction is in progress.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5671e41139c9cf87.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Design/Transactions/TransactionStack.cs:142
}
/// <inheritdoc/>
public IEnumerable<IReadOnlyTransaction> RetrieveAllTransactions()
{
return transactions;
}
public void CompleteTransaction(Transaction transaction)
{
lock (lockObject)
{
try
{
if (transactionsInProgress.Count == 0)
throw new TransactionException("There is not transaction in progress in the transaction stack.");
if (transaction != transactionsInProgress.Pop())
throw new TransactionException("The transaction being completed is not that last created transaction.");
// Check if we're completing the last transaction
TransactionInProgress = transactionsInProgress.Count > 0;
// Ignore the transaction if it is empty
if (transaction.IsEmpty)
return;
// If this transaction has no effect, discard it.
if (transaction.Operations.All(x => !x.HasEffect))
return;
// If we're not the last transaction, consider this transaction as an operation of its parent transaction
if (TransactionInProgress)
{
// Avoid useless nested transaction if we have a single operation inside.
PushOperation(transaction.Operations.Count == 1 ? transaction.Operations.Single() : transaction);
return;View on GitHub (pinned to 96fad776d2)