{"record":{"id":"0138f700a5f6e5ca","repo":"stride3d/stride","slug":"trying-to-complete-a-selection-transaction-but-no","errorCode":null,"errorMessage":"Trying to complete a selection transaction but no transaction in progress","messagePattern":"Trying to complete a selection transaction but no transaction in progress","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Core.Assets.Editor/Services/SelectionService.cs","lineNumber":197,"sourceCode":"                    {\n                        foreach (var collection in scope.Collections)\n                        {\n                            var descriptor = TypeDescriptorFactory.Default.Find(collection.GetType()) as CollectionDescriptor;\n                            descriptor?.Clear(collection);\n                        }\n                    }\n                }\n                finally\n                {\n                    PropertySelectionSuppressed = false;\n                }\n            }\n        }\n\n        private void CompleteTransaction()\n        {\n            if (currentTransaction == null)\n                throw new InvalidOperationException(\"Trying to complete a selection transaction but no transaction in progress\");\n\n            var newState = new SelectionState();\n            newState.SaveStates(scopes);\n\n            currentTransaction.Continue();\n            stack.PushOperation(new SelectionOperation(this, CurrentState, newState));\n            currentTransaction.Complete();\n            currentTransaction = null;\n\n            CurrentState = newState;\n        }\n    }\n}\n","sourceCodeStart":179,"sourceCodeEnd":211,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Core.Assets.Editor/Services/SelectionService.cs#L179-L211","documentation":"CompleteTransaction is the private commit step of a selection transaction; it throws InvalidOperationException when currentTransaction is null, meaning something asked to complete a transaction that was never begun or was already completed.","triggerScenarios":"Calling the completion path with no BeginTransaction — e.g. transaction already completed (double completion), an exception during the transaction skipped the begin, or nested completion after the current transaction was closed.","commonSituations":"Re-entrant selection updates completing the same transaction twice; exception in the middle of a transaction followed by a finally/complete call; UI events firing after the transaction ended.","solutions":["Ensure BeginTransaction is called exactly once per CompleteTransaction","Guard the completion path (check currentTransaction != null) or make complete idempotent","Track transaction state so teardown cannot complete an already-finished transaction"],"exampleFix":"// before\nprivate void CompleteTransaction()\n{\n    var newState = new SelectionState();\n// after\nprivate void CompleteTransaction()\n{\n    if (currentTransaction == null) return; // nothing to complete\n    var newState = new SelectionState();","handlingStrategy":"try-catch","validationCode":"if (currentTransaction == null) return; // no active transaction to complete","typeGuard":"bool HasActiveTransaction => currentTransaction != null;","tryCatchPattern":"try { CompleteTransaction(); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"no transaction in progress\")) { /* tolerate double-complete during teardown */ }","preventionTips":["Pair Begin/CompleteTransaction strictly in begin/finally blocks","Add a transaction-depth counter to prevent nested or double completion","Cancel (rather than complete) on exception paths that abort the transaction"],"tags":["invalid-operation","state-machine","transaction"],"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"}