stride3d/stride · error · TransactionException
Unable to rollforward. This method cannot be invoked when…
Error message
Unable to rollforward. This method cannot be invoked when CanRollforward is false.
What it means
TransactionStack.Rollforward() can only redo a transaction when CanRollforward is true, which requires the redo position (currentPosition) to be below the top of the history. This error is thrown when Rollforward is called with nothing left to redo.
Solutions
- Check transactionStack.CanRollforward before calling Rollforward.
- Disable/gray out the Redo action when CanRollforward is false (listen to property-change updates).
- Update UI state after each Rollback/Rollforward so the guard stays accurate.
- Catch TransactionException around Rollforward as a defensive fallback for concurrent redo triggers.
Example fix
// before
stack.Rollforward();
// after
if (stack.CanRollforward)
stack.Rollforward(); Defensive patterns
Strategy: validation
Validate before calling
if (transactionStack.CanRollforward)
transactionStack.Rollforward(); Type guard
bool CanRedo(TransactionStack stack) => stack.CanRollforward;
Try / catch
try
{
transactionStack.Rollforward();
}
catch (TransactionException ex) when (ex.Message.Contains("CanRollforward is false"))
{
// nothing to redo; update UI state
} Prevention
- Gate redo commands on CanRollforward.
- Subscribe to CanRollforward change notifications to enable/disable UI.
- Refresh guards after every rollback/rollforward/clear.
When it happens
Trigger: Calling transactionStack.Rollforward() when currentPosition is at the end of the transactions list (no undone transactions to redo, or history was cleared).
Common situations: Redo button/action invoked when there is nothing to redo; calling Rollforward after new operations reset the redo range; calling it on a fresh or Clear()ed stack.
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. A transaction is in progress.
- Unable to rollback. 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/c83c3a9caac7ac86.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Design/Transactions/TransactionStack.cs:247
try
{
lastTransaction.Interface.Rollback();
}
finally
{
RollInProgress = false;
}
TransactionRollbacked?.Invoke(this, new TransactionEventArgs(lastTransaction));
}
}
/// <inheritdoc/>
public void Rollforward()
{
lock (lockObject)
{
if (!CanRollforward)
throw new TransactionException("Unable to rollforward. This method cannot be invoked when CanRollforward is false.");
if (RollInProgress)
throw new TransactionException("Unable to rollforward. 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.Rollforward();
}
finally
{
RollInProgress = false;
}
TransactionRollforwarded?.Invoke(this, new TransactionEventArgs(lastTransaction));
}
}View on GitHub (pinned to 96fad776d2)