{"record":{"id":"f92c5601a99c925f","repo":"stride3d/stride","slug":"unable-to-rollback-a-transaction-is-in-progress","errorCode":null,"errorMessage":"Unable to rollback. A transaction is in progress.","messagePattern":"Unable to rollback\\. A transaction is in progress\\.","errorType":"exception","errorClass":"TransactionException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Design/Transactions/TransactionStack.cs","lineNumber":225,"sourceCode":"                {\n                    foreach (var parentTransaction in transactionsInProgress.Reverse())\n                        parentTransaction.Complete();\n                }\n            }\n        }\n    }\n\n    /// <inheritdoc/>\n    public void Rollback()\n    {\n        lock (lockObject)\n        {\n            if (!CanRollback)\n                throw new TransactionException(\"Unable to rollback. This method cannot be invoked when CanRollback is false.\");\n            if (RollInProgress)\n                throw new TransactionException(\"Unable to rollback. A rollback or rollforward operation is already in progress.\");\n            if (transactionsInProgress.Count > 0)\n                throw new TransactionException(\"Unable to rollback. A transaction is in progress.\");\n\n            var lastTransaction = transactions[--currentPosition];\n            RollInProgress = true;\n            try\n            {\n                lastTransaction.Interface.Rollback();\n            }\n            finally\n            {\n                RollInProgress = false;\n            }\n            TransactionRollbacked?.Invoke(this, new TransactionEventArgs(lastTransaction));\n        }\n    }\n\n    /// <inheritdoc/>\n    public void Rollforward()\n    {","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Design/Transactions/TransactionStack.cs#L207-L243","documentation":"Rollback() cannot run while a transaction is still in progress (created but not ended); the transactionsInProgress stack must be empty because undoing history mid-transaction would corrupt the transaction state. This error is thrown when Rollback is called while transactionsInProgress.Count > 0.","triggerScenarios":"Calling transactionStack.Rollback() between CreateTransaction/PushTransaction and the matching EndTransaction call.","commonSituations":"Undo triggered by UI while a batch/compound edit is still being recorded; an inner transaction leaked after an exception left EndTransaction uncalled; long-running transactions spanning user interactions.","solutions":["Ensure EndTransaction is called (try/finally) for every open transaction before allowing rollback.","Close or roll back the in-progress transaction scope explicitly before invoking Rollback.","Fix exception paths that leak open transactions (wrap scopes in using/finally).","Keep transactions short-lived; do not hold them open across user-driven undo commands."],"exampleFix":"// before\nusing (var tx = stack.CreateTransaction())\n{\n    stack.Rollback(); // invalid: tx still open\n}\n\n// after\nusing (var tx = stack.CreateTransaction())\n{\n    // record operations\n}\nstack.Rollback(); // only after transaction ended","handlingStrategy":"validation","validationCode":"if (transactionStack.CanRollback && !transactionStack.TransactionInProgress)\n    transactionStack.Rollback();","typeGuard":"bool CanUndoSafely(TransactionStack stack) => stack.CanRollback && !stack.TransactionInProgress;","tryCatchPattern":"try\n{\n    transactionStack.Rollback();\n}\ncatch (TransactionException ex) when (ex.Message.Contains(\"A transaction is in progress\"))\n{\n    // end the open transaction before retrying\n}","preventionTips":["Close transactions with try/finally around every scope.","Do not hold transactions open across UI undo commands.","Keep transaction lifetimes short and explicit."],"tags":["transactions","undo-redo","invalid-state"],"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"}