stride3d/stride · error · TransactionException

Unable to clear. A rollback or rollforward operation is in…

Error message

Unable to clear. A rollback or rollforward operation is in progress.

What it means

TransactionStack.Clear() wipes all transactions from the undo/redo history, but it must not run while a rollback or rollforward is executing, because Clear would mutate the transaction list the rollback/rollforward loop is iterating. The stack throws this error when Clear is called while RollInProgress is true.

Solutions

  1. Defer Clear() until after the rollback/rollforward completes (e.g. queue it and run after Rollback returns).
  2. Remove the Clear call from any code executed inside transaction rollback/rollforward handlers.
  3. If Clear is triggered by events, check a RollInProgress flag on the stack before calling Clear.
  4. Synchronize cross-thread calls so Clear and Rollback never overlap.

Example fix

// before
void OnHistoryResetRequested() => stack.Clear();

// after
void OnHistoryResetRequested()
{
    if (!stack.RollInProgress)
        stack.Clear();
    else
        pendingClear = true; // clear after rollback finishes
}
Defensive patterns

Strategy: validation

Validate before calling

if (transactionStack.RollInProgress)
    throw new InvalidOperationException("Cannot clear history during rollback/rollforward.");
transactionStack.Clear();

Type guard

bool CanClearHistory(TransactionStack stack) => !stack.RollInProgress;

Try / catch

try
{
    transactionStack.Clear();
}
catch (TransactionException ex) when (ex.Message.Contains("rollback or rollforward"))
{
    // retry after the roll operation completes
}

Prevention

When it happens

Trigger: Calling transactionStack.Clear() from inside a transaction's Rollback() or Rollforward() handler, or from another thread while a rollback/rollforward is running.

Common situations: Undo/redo callbacks that try to reset history; UI event handlers firing Clear while a rollback animation/operation is still in flight; re-entrant calls during Rollback/Rollforward.

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


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/c6c7d862d7858cce. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Design/Transactions/TransactionStack.cs:114

        {
            if (transactionsInProgress.Count == 0)
                throw new TransactionException("There is no transaction in progress in the transaction stack.");

            if (!operation.HasEffect)
                return;

            var transaction = transactionsInProgress.Peek();
            transaction.PushOperation(operation);
        }
    }

    /// <inheritdoc/>
    public void Clear()
    {
        lock (lockObject)
        {
            if (RollInProgress)
                throw new TransactionException("Unable to clear. A rollback or rollforward operation is in progress.");

            foreach (var transaction in transactions)
            {
                transaction.Interface.Freeze();
            }
            transactions.Clear();
            currentPosition = 0;
            Cleared?.Invoke(this, EventArgs.Empty);
        }
    }

    /// <inheritdoc/>
    public IEnumerable<IReadOnlyTransaction> RetrieveAllTransactions()
    {
        return transactions;
    }

    public void CompleteTransaction(Transaction transaction)

View on GitHub (pinned to 96fad776d2)