CronTriggerPayloadValidator only catches Cronos.CronFormatException — misses Quartz FormatException after CronParser swap
Summary
CronTriggerPayloadValidator validates cron by calling ICronParser.GetNextOccurrence, but only catches Cronos.CronFormatException. When Quartz is installed, QuartzSchedulerFeature swaps ICronParser to QuartzCronParser, whose Quartz.NET CronExpression throws FormatException on invalid input — so invalid Quartz-dialect cron can escape validation (or fail later at indexing) instead of producing a clean WorkflowValidationError.
Evidence
Elsa.Scheduling/TriggerPayloadValidators/CronTriggerPayloadValidator.cs:
try
{
cronParser.GetNextOccurrence(payload.CronExpression);
}
catch (CronFormatException ex) // Cronos-only
{
validationErrors.Add(new("Error when parsing cron expression: " + ex.Message,
trigger.ActivityId));
}Elsa.Scheduling.Quartz/Services/QuartzCronParser.cs:
public DateTimeOffset GetNextOccurrence(string expression)
{
var schedule = new CronExpression(expression); // throws FormatException on bad input
...
}Related incomplete wiring (same theme, not required for this fix): Hangfire scheduler feature does not swap ICronParser (stays Cronos IncludeSeconds), while Quartz does and retitles the Cron activity input as Quartz dialect — validators must not assume Cronos exception types once ICronParser is swappable.
Why not a duplicate
- elsa-extensions #198 (closed): Hangfire interval→cron / startAt — different surface.
- Not elsa-core #4509 (Elsa 2 temporal Hangfire).
- Not discussion-only empty-cron publish threads.
Concrete validator ↔ parser contract break after the Quartz parser swap.
Proposed direction (subtractive)
- Catch a parser-agnostic failure (
FormatException, or a small Elsa wrapper that allICronParserimplementations throw), and map toWorkflowValidationError. - Optionally add
ICronParser.TryGetNextOccurrence/Validateso callers do not catch implementation exceptions. - Test: with
QuartzCronParserregistered, invalid Quartz cron yields a validation error rather than an uncaughtFormatException.
Milestone: leave unset for Triage / Crew Lead.
Related
- Quartz
ICronParserswap inElsa.Scheduling.Quartz - Hangfire still on Cronos parser (dialect asymmetry — soft follow-up only)
Source: elsa-workflows/elsa-core