elsa-workflows/elsa-core · error · ArgumentException
A User Task title is required.
Error message
A User Task title is required.
What it means
UserTask.Normalize validates and defaults the task model before persistence. Every user task must have a non-whitespace Title; Normalize throws ArgumentException naming the Title parameter when it is missing. This is a model-invariant check performed when the task record is built.
Solutions
- Provide a non-empty Title when creating the UserTask.
- Default the title from another field (e.g., activity/display name) if a blank value is acceptable in your domain.
- Validate at the API/DTO boundary before mapping into the UserTask model.
Example fix
// before
var task = new UserTask { Actions = { new UserTaskAction("Approve", "Approve") } };
task.Normalize(); // throws
// after
var task = new UserTask { Title = "Review pull request", Actions = { new UserTaskAction("Approve", "Approve") } };
task.Normalize(); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(task.Title))
return Results.ValidationProblem(new Dictionary<string, string[]> { [nameof(UserTask.Title)] = ["Title is required."] }); Type guard
bool HasTitle(UserTask t) => !string.IsNullOrWhiteSpace(t.Title);
Try / catch
try
{
task.Normalize();
}
catch (ArgumentException ex) when (ex.ParamName == nameof(UserTask.Title))
{
return Results.ValidationProblem(new { title = new[] { ex.Message } });
} Prevention
- Make Title a required field in create/update DTOs.
- Default the title from workflow activity display names when not user-supplied.
- Trim inputs before assignment to avoid whitespace-only titles.
When it happens
Trigger: Constructing or completing a UserTask with Title null, empty, or whitespace-only and then invoking Normalize (directly or via create/save flows).
Common situations: UI forms that allow blank titles; API clients omitting the title field; deserialization from external data sources where the title column was empty.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- User Task action keys and labels are required.
- A configuration key is required.
- A conversation ID is required. (Parameter 'conversation')
- A conversation ID is required. (Parameter 'conversation')
- A conversation user ID is required. (Parameter…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/84643a0cc4cf61ef.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.UserTasks/Models/UserTaskModels.cs:207
public bool AllowManagerExclusionOverride { get; init; }
public int Priority { get; init; } = 50;
public DateTimeOffset? DueAt { get; init; }
public string? Instructions { get; init; }
public JsonElement? TaskData { get; init; }
public UserTaskFormReference? FormReference { get; init; }
public IReadOnlyCollection<UserTaskAction> Actions { get; init; } = [];
public IReadOnlyCollection<UserTaskInvitationDefinition> Invitations { get; init; } = [];
public bool EnableTimeoutOutcome { get; init; }
public bool EnableCancellationOutcome { get; init; }
public UserTaskDefinitionSnapshot Normalize()
{
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 UserTaskView on GitHub (pinned to fe9217bdfa)