stride3d/stride · error · InvalidOperationException
A transaction failed to be created.
Error message
A transaction failed to be created.
What it means
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.
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
Defensive patterns
Strategy: try-catch
Validate before calling
if (undoRedoService is not UndoRedoService) throw new InvalidOperationException("Unverified IUndoRedoService in use."); Try / catch
try { vm.Update(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("transaction failed to be created"))
{ log.LogError(ex, "UndoRedoService.CreateTransaction returned null"); } Prevention
- Use the stock UndoRedoService implementation
- Never return null from IUndoRedoService.CreateTransaction
- Cover transaction creation with unit tests
When it happens
Trigger: 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.
Common situations: A custom or broken IUndoRedoService implementation returning null; an exception thrown between transaction creation and use; misconfigured service provider returning a degenerate undo service.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- A PackageViewModel cannot contain two isntances of…
- The given IViewModelServiceProvider instance does not…
- IsObjectReference returned true for an object that is not…
- Asset of type was migrated, but still its new version…
- Package RootDirectory is null
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/1cafa3465c29e8cb.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation/ViewModels/EditableViewModel.cs:232
if (!EqualityComparer<T>.Default.Equals(field, value))
{
ITransaction? transaction = null;
if (!UndoRedoService.UndoRedoInProgress && createTransaction)
{
transaction = UndoRedoService.CreateTransaction();
var concatPropertyName = string.Join(", ", propertyNames.Where(x => !uncancellableChanges.Contains(x)).Select(s => $"'{s}'"));
UndoRedoService.SetName(transaction, $"Update property {concatPropertyName}");
}
try
{
return base.SetValue(ref field, value, updateAction, propertyNames);
}
finally
{
if (!UndoRedoService.UndoRedoInProgress && createTransaction)
{
if (transaction == null)
throw new InvalidOperationException("A transaction failed to be created.");
transaction.Complete();
}
}
}
return false;
}
private bool SetValue(Func<bool>? hasChangedFunction, Action? updateAction, bool createTransaction, params string[] propertyNames)
{
if (propertyNames.Length == 0)
throw new ArgumentOutOfRangeException(nameof(propertyNames), "This method must be invoked with at least one property name.");
if (hasChangedFunction == null || hasChangedFunction())
{
ITransaction? transaction = null;
if (!UndoRedoService.UndoRedoInProgress && createTransaction)
{
transaction = UndoRedoService.CreateTransaction();View on GitHub (pinned to 96fad776d2)