{"record":{"id":"1cafa3465c29e8cb","repo":"stride3d/stride","slug":"a-transaction-failed-to-be-created","errorCode":null,"errorMessage":"A transaction failed to be created.","messagePattern":"A transaction failed to be created\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation/ViewModels/EditableViewModel.cs","lineNumber":232,"sourceCode":"        if (!EqualityComparer<T>.Default.Equals(field, value))\n        {\n            ITransaction? transaction = null;\n            if (!UndoRedoService.UndoRedoInProgress && createTransaction)\n            {\n                transaction = UndoRedoService.CreateTransaction();\n                var concatPropertyName = string.Join(\", \", propertyNames.Where(x => !uncancellableChanges.Contains(x)).Select(s => $\"'{s}'\"));\n                UndoRedoService.SetName(transaction, $\"Update property {concatPropertyName}\");\n            }\n            try\n            {\n                return base.SetValue(ref field, value, updateAction, propertyNames);\n            }\n            finally\n            {\n                if (!UndoRedoService.UndoRedoInProgress && createTransaction)\n                {\n                    if (transaction == null)\n                        throw new InvalidOperationException(\"A transaction failed to be created.\");\n                    transaction.Complete();\n                }\n            }\n        }\n        return false;\n    }\n\n    private bool SetValue(Func<bool>? hasChangedFunction, Action? updateAction, bool createTransaction, params string[] propertyNames)\n    {\n        if (propertyNames.Length == 0)\n            throw new ArgumentOutOfRangeException(nameof(propertyNames), \"This method must be invoked with at least one property name.\");\n\n        if (hasChangedFunction == null || hasChangedFunction())\n        {\n            ITransaction? transaction = null;\n            if (!UndoRedoService.UndoRedoInProgress && createTransaction)\n            {\n                transaction = UndoRedoService.CreateTransaction();","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation/ViewModels/EditableViewModel.cs#L214-L250","documentation":"SetValue starts an undo transaction before mutating state and, in the finally block, requires that a transaction was actually created whenever transaction creation was requested. If it is still null, something is wrong inside the undo/redo service, and the library fails with InvalidOperationException to expose the broken invariant rather than silently skipping undo tracking.","triggerScenarios":"UndoRedoService.UndoRedoInProgress is false and createTransaction is true, but the service's CreateTransaction returned null or threw before assignment, leaving the transaction variable null in the finally block.","commonSituations":"A custom or broken IUndoRedoService implementation returning null; an exception thrown between transaction creation and use; misconfigured service provider returning a degenerate undo service.","solutions":["Fix or replace the IUndoRedoService so CreateTransaction always returns a valid transaction when not already in undo/redo","Check that no exception path in the try block aborts transaction creation silently","Ensure the service is the stock UndoRedoService or a well-tested implementation","Log/diagnose why CreateTransaction yielded null"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (undoRedoService is not UndoRedoService) throw new InvalidOperationException(\"Unverified IUndoRedoService in use.\");","typeGuard":null,"tryCatchPattern":"try { vm.Update(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"transaction failed to be created\"))\n{ log.LogError(ex, \"UndoRedoService.CreateTransaction returned null\"); }","preventionTips":["Use the stock UndoRedoService implementation","Never return null from IUndoRedoService.CreateTransaction","Cover transaction creation with unit tests"],"tags":["transaction","invariant","undo","viewmodel"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}