elsa-workflows/elsa-core · error · ArgumentException

Invitation actions must be configured User Task actions.

Error message

Invitation actions must be configured User Task actions.

What it means

Normalize() cross-checks that every AllowedActions entry on each invitation references an action key that exists in the definition's Actions list (case-insensitive). If an invitation names an action that is not configured, the ArgumentException is thrown. This keeps invitations from granting actions the task cannot deliver.

Solutions

  1. Update each invitation's AllowedActions to reference existing action keys after changing Actions.
  2. Validate and fix definitions after any rename/migration of action keys.
  3. Trim and normalize action keys when authoring to avoid whitespace/case mismatches.

Example fix

// before
Actions = [new() { Key = "Reject", Label = "Reject" }],
Invitations = [new() { VerifierName = "Managers", AllowedActions = ["Rejected"] }]
// after
Invitations = [new() { VerifierName = "Managers", AllowedActions = ["Reject"] }]
Defensive patterns

Strategy: validation

Validate before calling

var keys = definition.Actions.Select(a => a.Key).ToHashSet(StringComparer.OrdinalIgnoreCase);
var dangling = definition.Invitations.SelectMany(i => i.AllowedActions).Where(a => !keys.Contains(a)).ToList();
if (dangling.Count > 0) throw new InvalidOperationException($"Unknown action keys: {string.Join(", ", dangling)}");

Try / catch

try { definition = definition.Normalize(); }
catch (ArgumentException ex) when (ex.Message.Contains("configured User Task actions")) { /* re-map invitation actions */ }

Prevention

When it happens

Trigger: Renaming or deleting a User Task action (e.g. 'Rejected' → 'Reject') without updating Invitations' AllowedActions; hand-authored definitions where invitations were copied from another task; typo in an allowed action key.

Common situations: Definition versioning/migration where action sets changed; copy-paste between task definitions; spelling differences like 'approve ' with a trailing space.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.UserTasks/Models/UserTaskModels.cs:219

    {
        var actions = Actions.Count == 0
            ? [new UserTaskAction("Complete", "Complete")]
            : Actions;

        if (string.IsNullOrWhiteSpace(Title))
            throw new ArgumentException("A User Task title is required.", nameof(Title));
        if (actions.Any(x => string.IsNullOrWhiteSpace(x.Key) || string.IsNullOrWhiteSpace(x.Label)))
            throw new ArgumentException("User Task action keys and labels are required.", nameof(Actions));
        if (actions.Any(x => string.Equals(x.Key, "Timeout", StringComparison.OrdinalIgnoreCase) || string.Equals(x.Key, "Cancelled", StringComparison.OrdinalIgnoreCase)))
            throw new ArgumentException("Timeout and Cancelled are reserved User Task action keys.");
        if (actions.Select(x => x.Key).Distinct(StringComparer.OrdinalIgnoreCase).Count() != actions.Count)
            throw new ArgumentException("User Task action keys must be unique.");
        if (Priority is < 0 or > 100)
            throw new ArgumentOutOfRangeException(nameof(Priority), "Priority must be between 0 and 100.");
        if (Invitations.Any(x => string.IsNullOrWhiteSpace(x.VerifierName) || x.AllowedActions.Count == 0 || x.AllowedActions.Any(string.IsNullOrWhiteSpace)))
            throw new ArgumentException("Invitation verifier names and allowed actions are required.", nameof(Invitations));
        if (Invitations.Any(invitation => invitation.AllowedActions.Any(allowed => !actions.Any(action => string.Equals(action.Key, allowed, StringComparison.OrdinalIgnoreCase)))))
            throw new ArgumentException("Invitation actions must be configured User Task actions.", nameof(Invitations));

        return this with { Actions = actions };
    }
}

public sealed class UserTask
{
    public string Id { get; set; } = Guid.NewGuid().ToString("N");
    public string TenantId { get; set; } = "";
    public string WorkflowDefinitionId { get; set; } = "";
    public string? WorkflowDefinitionName { get; set; }
    public int? WorkflowDefinitionVersion { get; set; }
    public string WorkflowInstanceId { get; set; } = "";
    /// <summary>A safe, host-authored instance reference (correlation ID or instance name). Never a bookmark or token.</summary>
    public string? WorkflowInstanceReference { get; set; }
    public string ActivityInstanceId { get; set; } = "";
    public string BookmarkId { get; set; } = "";
    public string MaterializationKey { get; set; } = "";

View on GitHub (pinned to fe9217bdfa)