elsa-workflows/elsa-core · error · InvalidOperationException

No alterations found in the transient properties.

Error message

No alterations found in the transient properties.

What it means

RunAlterationsMiddleware is a workflow middleware that expects the alterations to have been staged in WorkflowExecutionContext.TransientProperties under AlterationsPropertyKey before it runs. If the key is absent, it throws InvalidOperationException because there is nothing to execute — the middleware was installed without a caller having prepared the alterations.

Solutions

  1. Use the intended API for running alterations (e.g., the alterations manager/service) which seeds both transient properties before invoking the workflow.
  2. If registering the middleware manually, set context.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsPropertyKey, alterations) before execution.
  3. Audit middleware registration so RunAlterationsMiddleware is only attached to workflows actually being alteration-run.
  4. For resumed instances, ensure the seeding code runs again on resume.

Example fix

// before
workflowBuilder.AddMiddleware<RunAlterationsMiddleware>(); // runs for every workflow

// after
var alterations = new List<IAlteration> { new ReplaceActivity(...) };
context.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsPropertyKey, alterations);
context.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsLogPropertyKey, new AlterationLog());
await workflowRunner.RunAsync(workflow, context); // middleware now finds the data
Defensive patterns

Strategy: type-guard

Validate before calling

var hasAlterations = context.TransientProperties.GetValue(RunAlterationsMiddleware.AlterationsPropertyKey) is IEnumerable<IAlteration>;
if (!hasAlterations) throw new InvalidOperationException("Seed alterations before running the workflow.");

Type guard

bool TryGetAlterations(WorkflowExecutionContext ctx, out IEnumerable<IAlteration> alterations)
{
    var value = ctx.TransientProperties.GetValue(RunAlterationsMiddleware.AlterationsPropertyKey);
    alterations = value as IEnumerable<IAlteration>;
    return alterations != null;
}

Try / catch

try
{
    await workflowRunner.RunAsync(workflow, workflowState);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("No alterations found in the transient properties"))
{
    logger.LogError(ex, "RunAlterationsMiddleware ran without seeded alterations; check middleware registration.");
}

Prevention

When it happens

Trigger: Executing a workflow with RunAlterationsMiddleware registered in the pipeline while nothing set TransientProperties[AlterationsPropertyKey] (normally done via context.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsPropertyKey, alterations) before the workflow runs).

Common situations: Registering the middleware globally in middleware configuration instead of using the dedicated run-alterations entry point; calling WorkflowServer/runner APIs directly without the alterations bootstrap; refactoring away the code that set the property; running an altered workflow through a path that does not seed transient properties (e.g., a resumed/replayed instance).

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


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/c81a0175a5c6798c. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Alterations/Middleware/Workflows/RunAlterationsMiddleware.cs:20

using Elsa.Alterations.Core.Contracts;
using Elsa.Alterations.Core.Models;
using Elsa.Extensions;
using Elsa.Workflows;
using Elsa.Workflows.Pipelines.WorkflowExecution;

namespace Elsa.Alterations.Middleware.Workflows;

/// <summary>
/// Middleware that runs alterations.
/// </summary>
internal class RunAlterationsMiddleware(WorkflowMiddlewareDelegate next, IEnumerable<IAlterationHandler> handlers) : WorkflowExecutionMiddleware(next)
{
    public static readonly object AlterationsPropertyKey = new();
    public static readonly object AlterationsLogPropertyKey = new();

    public override async ValueTask InvokeAsync(WorkflowExecutionContext context)
    {
        var alterations = (IEnumerable<IAlteration>)(context.TransientProperties.GetValue(AlterationsPropertyKey) ?? throw new InvalidOperationException("No alterations found in the transient properties."));
        var log = (AlterationLog)(context.TransientProperties.GetValue(AlterationsLogPropertyKey) ?? throw new InvalidOperationException("No alteration log found in the transient properties."));
        await RunAsync(context, alterations, log, context.CancellationToken);
    }

    private async Task RunAsync(WorkflowExecutionContext workflowExecutionContext, IEnumerable<IAlteration> alterations, AlterationLog log, CancellationToken cancellationToken = default)
    {
        var commitActions = new List<Func<Task>>();

        foreach (var alteration in alterations)
        {
            // Find handlers.
            var supportedHandlers = handlers.Where(x => x.CanHandle(alteration)).ToList();

            foreach (var handler in supportedHandlers)
            {
                // Execute handler.
                var alterationContext = new AlterationContext(alteration, workflowExecutionContext, log, cancellationToken);
                await handler.HandleAsync(alterationContext);

View on GitHub (pinned to fe9217bdfa)