{"record":{"id":"c81a0175a5c6798c","repo":"elsa-workflows/elsa-core","slug":"no-alterations-found-in-the-transient-properties","errorCode":null,"errorMessage":"No alterations found in the transient properties.","messagePattern":"No alterations found in the transient properties\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Alterations/Middleware/Workflows/RunAlterationsMiddleware.cs","lineNumber":20,"sourceCode":"using Elsa.Alterations.Core.Contracts;\nusing Elsa.Alterations.Core.Models;\nusing Elsa.Extensions;\nusing Elsa.Workflows;\nusing Elsa.Workflows.Pipelines.WorkflowExecution;\n\nnamespace Elsa.Alterations.Middleware.Workflows;\n\n/// <summary>\n/// Middleware that runs alterations.\n/// </summary>\ninternal class RunAlterationsMiddleware(WorkflowMiddlewareDelegate next, IEnumerable<IAlterationHandler> handlers) : WorkflowExecutionMiddleware(next)\n{\n    public static readonly object AlterationsPropertyKey = new();\n    public static readonly object AlterationsLogPropertyKey = new();\n\n    public override async ValueTask InvokeAsync(WorkflowExecutionContext context)\n    {\n        var alterations = (IEnumerable<IAlteration>)(context.TransientProperties.GetValue(AlterationsPropertyKey) ?? throw new InvalidOperationException(\"No alterations found in the transient properties.\"));\n        var log = (AlterationLog)(context.TransientProperties.GetValue(AlterationsLogPropertyKey) ?? throw new InvalidOperationException(\"No alteration log found in the transient properties.\"));\n        await RunAsync(context, alterations, log, context.CancellationToken);\n    }\n\n    private async Task RunAsync(WorkflowExecutionContext workflowExecutionContext, IEnumerable<IAlteration> alterations, AlterationLog log, CancellationToken cancellationToken = default)\n    {\n        var commitActions = new List<Func<Task>>();\n\n        foreach (var alteration in alterations)\n        {\n            // Find handlers.\n            var supportedHandlers = handlers.Where(x => x.CanHandle(alteration)).ToList();\n\n            foreach (var handler in supportedHandlers)\n            {\n                // Execute handler.\n                var alterationContext = new AlterationContext(alteration, workflowExecutionContext, log, cancellationToken);\n                await handler.HandleAsync(alterationContext);","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Alterations/Middleware/Workflows/RunAlterationsMiddleware.cs#L2-L38","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","solutions":["Use the intended API for running alterations (e.g., the alterations manager/service) which seeds both transient properties before invoking the workflow.","If registering the middleware manually, set context.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsPropertyKey, alterations) before execution.","Audit middleware registration so RunAlterationsMiddleware is only attached to workflows actually being alteration-run.","For resumed instances, ensure the seeding code runs again on resume."],"exampleFix":"// before\nworkflowBuilder.AddMiddleware<RunAlterationsMiddleware>(); // runs for every workflow\n\n// after\nvar alterations = new List<IAlteration> { new ReplaceActivity(...) };\ncontext.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsPropertyKey, alterations);\ncontext.TransientProperties.SetValue(RunAlterationsMiddleware.AlterationsLogPropertyKey, new AlterationLog());\nawait workflowRunner.RunAsync(workflow, context); // middleware now finds the data","handlingStrategy":"type-guard","validationCode":"var hasAlterations = context.TransientProperties.GetValue(RunAlterationsMiddleware.AlterationsPropertyKey) is IEnumerable<IAlteration>;\nif (!hasAlterations) throw new InvalidOperationException(\"Seed alterations before running the workflow.\");","typeGuard":"bool TryGetAlterations(WorkflowExecutionContext ctx, out IEnumerable<IAlteration> alterations)\n{\n    var value = ctx.TransientProperties.GetValue(RunAlterationsMiddleware.AlterationsPropertyKey);\n    alterations = value as IEnumerable<IAlteration>;\n    return alterations != null;\n}","tryCatchPattern":"try\n{\n    await workflowRunner.RunAsync(workflow, workflowState);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"No alterations found in the transient properties\"))\n{\n    logger.LogError(ex, \"RunAlterationsMiddleware ran without seeded alterations; check middleware registration.\");\n}","preventionTips":["Use the dedicated alterations-run API instead of registering the middleware manually.","Seed transient properties immediately before invoking the workflow in a single helper.","Only attach RunAlterationsMiddleware to workflows that are part of an alteration run."],"tags":["workflow","alterations","middleware","transient-properties"],"backgroundTag":"internal-invariant-violation","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}