OrchardCMS/OrchardCore · error · ValidationException

The variable ' ' was used in the recipe but not defined…

Error message

The variable '{0}' was used in the recipe but not defined. Make sure you add the '{0}' variable in the '{1}' section of the recipe.

What it means

VariablesMethodProvider.GetVariableValueAsync resolves a recipe variable referenced by the [[VariableName]] syntax. If the named variable does not exist in the recipe's 'variables' section, it throws a ValidationException telling the author to define the variable. This fails fast during recipe execution rather than silently injecting null.

Solutions

  1. Add the missing variable to the recipe's "variables" section: "variables": { "MyVar": "value" }.
  2. Fix the reference typo in the step so it matches a declared variable name exactly (case included).
  3. If the value should come from user input at setup, declare it in the recipe parameters/setup settings instead of referencing an undeclared name.
  4. Search the recipe file for all [[...]] references and reconcile them against declared variables.

Example fix

// before (step references [[SiteName]] but variables section lacks it)
{
  "variables": { },
  "steps": [
    { "type": "settings", "values": { "SiteName": "[[SiteName]]" } }
  ]
}

// after
{
  "variables": { "SiteName": "My Site" },
  "steps": [
    { "type": "settings", "values": { "SiteName": "[[SiteName]]" } }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

var json = JsonNode.Parse(File.ReadAllText(recipePath));
var variables = json?["variables"]?.AsObject();
foreach (var reference in System.Text.RegularExpressions.Regex.Matches(
             json!.ToJsonString(), "\[\[(\w+)\]\]"))
{
    var name = reference.Groups[1].Value;
    if (variables?[name] == null)
        throw new Exception($"Recipe references undefined variable '{name}'");
}

Try / catch

try
{
    await recipeExecutor.ExecuteAsync(executionId, descriptor, environment, logger);
}
catch (ValidationException ex)
{
    logger.LogError(ex, "Recipe references an undefined variable: {Message}", ex.Message);
}

Prevention

When it happens

Trigger: A recipe step references a variable (e.g., [[MyVar]] in a script or parameter) that is not declared in the recipe's "variables" section, so VariablesMethodProvider looks it up in the variables dictionary and finds null.

Common situations: Typo in a [[VariableName]] reference vs. its declaration; a variable deleted from the 'variables' section while steps still reference it; copying steps from another recipe without copying the variables; case-sensitivity mismatch between reference and declaration.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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

Appendix: source

Thrown at src/OrchardCore/OrchardCore.Recipes.Core/VariablesMethodProvider.cs:46

    public IEnumerable<GlobalMethod> GetMethods()
    {
        yield return _globalMethod;
    }

    private static async Task<object> GetVariableValueAsync(
        IServiceProvider serviceProvider,
        JsonObject variables,
        List<IGlobalMethodProvider> scopedMethodProviders,
        string name)
    {
        var variable = variables[name];

        if (variable == null)
        {
            var S = serviceProvider.GetService<IStringLocalizer<VariablesMethodProvider>>();

            throw new ValidationException(S["The variable '{0}' was used in the recipe but not defined. Make sure you add the '{0}' variable in the '{1}' section of the recipe.", name, GlobalMethodName]);
        }

        var value = variable.Value<string>();

        // Replace variable value while the result returns another script.
        while (value.StartsWith('[') && value.EndsWith(']'))
        {
            value = value.Trim('[', ']');
            value = (await ScriptingManager.EvaluateAsync(value, null, null, scopedMethodProviders) ?? "").ToString();
            variables[name] = value;
        }

        return value;
    }
}

View on GitHub (pinned to 4306c0717f)