{"record":{"id":"5671e41139c9cf87","repo":"stride3d/stride","slug":"the-transaction-being-completed-is-not-that-last-created","errorCode":null,"errorMessage":"The transaction being completed is not that last created transaction.","messagePattern":"The transaction being completed is not that last created transaction\\.","errorType":"exception","errorClass":"TransactionException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Design/Transactions/TransactionStack.cs","lineNumber":142,"sourceCode":"    }\n\n    /// <inheritdoc/>\n    public IEnumerable<IReadOnlyTransaction> RetrieveAllTransactions()\n    {\n        return transactions;\n    }\n\n    public void CompleteTransaction(Transaction transaction)\n    {\n        lock (lockObject)\n        {\n            try\n            {\n                if (transactionsInProgress.Count == 0)\n                    throw new TransactionException(\"There is not transaction in progress in the transaction stack.\");\n\n                if (transaction != transactionsInProgress.Pop())\n                    throw new TransactionException(\"The transaction being completed is not that last created transaction.\");\n\n                // Check if we're completing the last transaction\n                TransactionInProgress = transactionsInProgress.Count > 0;\n\n                // Ignore the transaction if it is empty\n                if (transaction.IsEmpty)\n                    return;\n\n                // If this transaction has no effect, discard it.\n                if (transaction.Operations.All(x => !x.HasEffect))\n                    return;\n\n                // If we're not the last transaction, consider this transaction as an operation of its parent transaction\n                if (TransactionInProgress)\n                {\n                    // Avoid useless nested transaction if we have a single operation inside.\n                    PushOperation(transaction.Operations.Count == 1 ? transaction.Operations.Single() : transaction);\n                    return;","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Design/Transactions/TransactionStack.cs#L124-L160","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstack.EndTransaction(outerTx); // innerTx still open\n\n// after\nstack.EndTransaction(innerTx); // close innermost first\nstack.EndTransaction(outerTx);","handlingStrategy":"validation","validationCode":"// ensure LIFO order: only end the innermost transaction\nif (transactionStack.TransactionInProgress && transaction == innermostOpenTransaction)\n    transactionStack.EndTransaction(transaction);","typeGuard":"bool IsInnermost(Transaction transaction, Transaction innermost) => ReferenceEquals(transaction, innermost);","tryCatchPattern":"try\n{\n    transactionStack.EndTransaction(transaction);\n}\ncatch (TransactionException ex) when (ex.Message.Contains(\"not that last created transaction\"))\n{\n    // find and close the leaked inner transaction first\n}","preventionTips":["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."],"tags":["transactions","undo-redo","nesting"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}