#8184·elsa-core

CronTriggerPayloadValidator only catches Cronos.CronFormatException — misses Quartz FormatException after CronParser swap

Author: sfmskywalkerCreated Sep 19, 2026Updated Sep 19, 2026
Labelsbugcoreprio lowelsa 3testtriaged

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:

csharp
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:

csharp
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)

  1. Catch a parser-agnostic failure (FormatException, or a small Elsa wrapper that all ICronParser implementations throw), and map to WorkflowValidationError.
  2. Optionally add ICronParser.TryGetNextOccurrence / Validate so callers do not catch implementation exceptions.
  3. Test: with QuartzCronParser registered, invalid Quartz cron yields a validation error rather than an uncaught FormatException.

Milestone: leave unset for Triage / Crew Lead.

Related

  • Quartz ICronParser swap in Elsa.Scheduling.Quartz
  • Hangfire still on Cronos parser (dialect asymmetry — soft follow-up only)

Source: elsa-workflows/elsa-core