elsa-workflows/elsa-core · error · NotSupportedException

The BPMN continuation

Error message

The BPMN continuation '{evaluation.Continuation.GetType().Name}' is not supported by this host.

What it means

BpmnScopeHost.ApplyAsync switches over the interpreter's continuation types (Complete, Defer, Fault, …); any unrecognized continuation type falls into the default branch and throws NotSupportedException. Like the command applier's guard, this protects against version skew where a newer interpreter emits a continuation the host does not understand.

Solutions

  1. Align all Elsa.Bpmn package versions so host and interpreter come from the same release.
  2. If you defined a custom BpmnContinuation subclass, extend ApplyAsync's switch to handle it.
  3. Rebuild the application after upgrading to avoid stale mixed assemblies.

Example fix

// before
<PackageReference Include="Elsa.Bpmn.Interpreter" Version="3.2.0" />
<PackageReference Include="Elsa.Bpmn.Hosting" Version="3.1.0" />
// after
<PackageReference Include="Elsa.Bpmn.Interpreter" Version="3.2.0" />
<PackageReference Include="Elsa.Bpmn.Hosting" Version="3.2.0" />
Defensive patterns

Strategy: try-catch

Try / catch

try { await host.EvaluateAsync(...); }
catch (NotSupportedException ex) when (ex.Message.StartsWith("The BPMN continuation")) { log.LogCritical(ex, "Version skew between interpreter and host"); throw; }

Prevention

When it happens

Trigger: A BpmnEvaluation whose Continuation object is of a type added by a newer interpreter version than this BpmnScopeHost supports (mixed package versions).

Common situations: Partially upgraded Elsa.Bpmn packages where the interpreter DLL is newer than the hosting DLL; custom continuations introduced by an extension the host does not handle.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.Bpmn/Hosting/BpmnScopeHost.cs:219

            await ApplyAsync(memory, evaluation);
        });

    private async ValueTask ApplyAsync(BpmnScopeMemory memory, BpmnEvaluation evaluation)
    {
        await new BpmnCommandApplier(_context, _process, memory).ApplyAsync(evaluation.Commands);

        switch (evaluation.Continuation)
        {
            case BpmnContinuation.Complete complete:
                // The scope completes because the interpreter said so, never because it ran out of children.
                await _context.CompleteActivityAsync(new Outcomes(complete.Outcome));
                break;
            case BpmnContinuation.Defer:
                break;
            case BpmnContinuation.Fault fault:
                throw new BpmnScopeFaultException(fault.Code, fault.Message);
            default:
                throw new NotSupportedException($"The BPMN continuation '{evaluation.Continuation.GetType().Name}' is not supported by this host.");
        }
    }

    /// <summary>
    /// Projects every diagnostic the interpreter has appended since the last evaluation onto this scope's own
    /// execution log, keyed by element id. Under Option A only bound work has an activity id, so a gateway, an
    /// intermediate event or a sequence flow has nothing else in the journal to say where a token went; this is
    /// write-only and never read back by the interpreter or this host.
    /// </summary>
    /// <remarks>
    /// Runs on <see cref="_context"/> — this scope's own context — and never a child's: the diagnostic describes
    /// this scope's decision about a child, and the child may already be torn down by the time this runs. Called
    /// with the evaluation's own <see cref="BpmnEvaluation.State"/>, before <c>Prune()</c> caps
    /// <see cref="BpmnExecutionState.Diagnostics"/> at 200 entries, because projecting from what was actually
    /// persisted would lose whatever pruning already dropped. The last diagnostic id it has projected is kept in
    /// <see cref="BpmnScopeMemory.DiagnosticsCursorPropertyKey"/> so a resumed scope does not re-emit one a
    /// previous evaluation already turned into a journal entry.
    /// </remarks>

View on GitHub (pinned to fe9217bdfa)