stride3d/stride · error · TransactionException
Unable to rollback. A transaction is in progress.
Error message
Unable to rollback. A transaction is in progress.
What it means
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.
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.
Example fix
// before
using (var tx = stack.CreateTransaction())
{
stack.Rollback(); // invalid: tx still open
}
// after
using (var tx = stack.CreateTransaction())
{
// record operations
}
stack.Rollback(); // only after transaction ended Defensive patterns
Strategy: validation
Validate before calling
if (transactionStack.CanRollback && !transactionStack.TransactionInProgress)
transactionStack.Rollback(); Type guard
bool CanUndoSafely(TransactionStack stack) => stack.CanRollback && !stack.TransactionInProgress;
Try / catch
try
{
transactionStack.Rollback();
}
catch (TransactionException ex) when (ex.Message.Contains("A transaction is in progress"))
{
// end the open transaction before retrying
} Prevention
- Close transactions with try/finally around every scope.
- Do not hold transactions open across UI undo commands.
- Keep transaction lifetimes short and explicit.
When it happens
Trigger: Calling transactionStack.Rollback() between CreateTransaction/PushTransaction and the matching EndTransaction call.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- There is no transaction in progress in the transaction…
- There is not transaction in progress in the transaction…
- Unable to rollback. This method cannot be invoked when…
- Unable to rollforward. This method cannot be invoked when…
- The transaction being completed is not that last created…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f92c5601a99c925f.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Design/Transactions/TransactionStack.cs:225
{
foreach (var parentTransaction in transactionsInProgress.Reverse())
parentTransaction.Complete();
}
}
}
}
/// <inheritdoc/>
public void Rollback()
{
lock (lockObject)
{
if (!CanRollback)
throw new TransactionException("Unable to rollback. This method cannot be invoked when CanRollback is false.");
if (RollInProgress)
throw new TransactionException("Unable to rollback. A rollback or rollforward operation is already in progress.");
if (transactionsInProgress.Count > 0)
throw new TransactionException("Unable to rollback. A transaction is in progress.");
var lastTransaction = transactions[--currentPosition];
RollInProgress = true;
try
{
lastTransaction.Interface.Rollback();
}
finally
{
RollInProgress = false;
}
TransactionRollbacked?.Invoke(this, new TransactionEventArgs(lastTransaction));
}
}
/// <inheritdoc/>
public void Rollforward()
{View on GitHub (pinned to 96fad776d2)