stride3d/stride · error · TransactionException

There is no transaction in progress in the transaction…

Error message

There is no transaction in progress in the transaction stack.

What it means

TransactionStack.PushOperation() requires an open transaction to attach the operation to. The stack throws this error when PushOperation is called while the transactionsInProgress stack is empty, meaning there is no active CreateTransaction context to push the operation onto. Operations must always be recorded inside a transaction scope.

Solutions

  1. Open a transaction with CreateTransaction (or PushTransaction) before calling PushOperation.
  2. Check TransactionStack.TransactionInProgress (or capture the transaction scope) before deferring PushOperation calls.
  3. Restructure deferred code so all operations are recorded before EndTransaction is invoked.
  4. Wrap PushOperation in try-catch on TransactionException as a last resort to ignore orphaned operations.

Example fix

// before
transactionStack.PushOperation(operation);

// after
if (transactionStack.TransactionInProgress)
    transactionStack.PushOperation(operation);
Defensive patterns

Strategy: validation

Validate before calling

if (!transactionStack.TransactionInProgress)
    throw new InvalidOperationException("No transaction in progress; call CreateTransaction before PushOperation.");
transactionStack.PushOperation(operation);

Type guard

bool HasOpenTransaction(TransactionStack stack) => stack.TransactionInProgress;

Try / catch

try
{
    transactionStack.PushOperation(operation);
}
catch (TransactionException ex) when (ex.Message.Contains("no transaction in progress"))
{
    // log and drop the orphaned operation
}

Prevention

When it happens

Trigger: Calling transactionStack.PushOperation(operation) without a prior CreateTransaction()/PushTransaction() call, or after the enclosing transaction was already completed via EndTransaction.

Common situations: Deferred/async code that records undo operations after the transaction has ended; forgetting to open a transaction before mutating an object tracked by the stack; an exception path that ended the transaction early while deferred callbacks still fire.

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/6ec583f44476123e. Report an issue: GitHub.

Appendix: source

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

            if ((flags & TransactionFlags.KeepParentsAlive) != 0)
            {
                foreach (var parentTransaction in transactionsInProgress)
                    parentTransaction.AddReference();
            }

            transactionsInProgress.Push(transaction);
            TransactionInProgress = true;
            return transaction;
        }
    }

    /// <inheritdoc/>
    public void PushOperation(Operation operation)
    {
        lock (lockObject)
        {
            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)

View on GitHub (pinned to 96fad776d2)