OrchardCMS/OrchardCore · error · NotSupportedException

The syntax isn't supported for ForEachTask.

Error message

The syntax {Syntax} isn't supported for ForEachTask.

What it means

ForEachTask evaluates its Items expression using the scripting syntax stored on the activity (Syntax). Only Liquid (via the Liquid expression evaluator) and JavaScript (via the script evaluator) are implemented; any other WorkflowScriptSyntax value falls through the switch arm and throws NotSupportedException. This guards against a misconfigured or newly added enum value being used before it has an implementation.

Solutions

  1. Set the ForEachTask activity's Syntax property to WorkflowScriptSyntax.Liquid and move the expression into the Liquid 'Items' (LiquidEnumerable) field.
  2. Alternatively set Syntax to WorkflowScriptSyntax.JavaScript and provide the expression in the 'Enumerable' (JavaScript) field.
  3. Inspect the stored workflow definition/activity properties for an invalid or legacy syntax value and correct or migrate it.
  4. If a new syntax was recently added to WorkflowScriptSyntax, rebuild/update the OrchardCore.Workflows module so the switch handles it, or file/wait for an implementation of that arm.

Example fix

// before
var forEach = new ForEachTask(); // Syntax left at default (unsupported value)
// after
var forEach = new ForEachTask
{
    Syntax = WorkflowScriptSyntax.Liquid,
    Items = new LiquidString { Expression = "{{ Model.UserNames | json }}" }
};
Defensive patterns

Strategy: validation

Validate before calling

// before executing
if (forEachTask.Syntax is not (WorkflowScriptSyntax.Liquid or WorkflowScriptSyntax.JavaScript))
    throw new InvalidOperationException($"ForEachTask requires Liquid or JavaScript syntax; got {forEachTask.Syntax}");

Type guard

static bool IsSupportedSyntax(WorkflowScriptSyntax s) => s is WorkflowScriptSyntax.Liquid or WorkflowScriptSyntax.JavaScript;

Try / catch

try { await activity.ExecuteAsync(workflowContext, activityContext); }
catch (NotSupportedException ex) { logger.LogError(ex, "ForEachTask syntax unsupported: {Syntax}", syntax); /* fail or fix activity */ }

Prevention

When it happens

Trigger: Executing a ForEachTask activity whose Syntax property is not WorkflowScriptSyntax.Liquid or WorkflowScriptSyntax.JavaScript, e.g. the enum default value (typically the first/0 member if it is not Liquid) left unset, a JSON workflow definition deserialized with an unknown/renamed syntax string, or a caller constructing ForEachTask programmatically without setting Syntax to a supported value.

Common situations: Hand-edited or generated workflow JSON with a stale syntax name after an SDK/module upgrade; a new WorkflowScriptSyntax member added upstream while the ForEachTask activity module was not rebuilt; code that news up ForEachTask and forgets to assign Syntax; data migration leaving old syntax values in stored activity properties.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/fedf0848501c1571. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.Workflows/Activities/ForEachTask.cs:87

    /// <summary>
    /// The current number of iterations executed.
    /// </summary>
    public int Index
    {
        get => GetProperty(() => 0);
        set => SetProperty(value);
    }

    public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
        => Outcome(S["Iterate"], S["Done"]);

    public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
    {
        var items = Syntax switch
        {
            WorkflowScriptSyntax.Liquid => await EvaluateLiquidEnumerableAsync(workflowContext),
            WorkflowScriptSyntax.JavaScript => (await _scriptEvaluator.EvaluateAsync(Enumerable, workflowContext)).ToList(),
            _ => throw new NotSupportedException($"The syntax {Syntax} isn't supported for ForEachTask.")
        };

        var count = items.Count;

        if (Index < count)
        {
            var current = Current = items[Index];

            // TODO: Implement nested scopes. See https://github.com/OrchardCMS/OrchardCore/projects/4#card-6992776
            workflowContext.Properties[LoopVariableName] = current;
            workflowContext.LastResult = current;
            Index++;

            return Outcome("Iterate");
        }
        else
        {
            Index = 0;

View on GitHub (pinned to 4306c0717f)