flowable/flowable-engine · error · FlowableException

Failed to parse scheduler expression:

Error message

Failed to parse scheduler expression: 

What it means

AdvancedSchedulerResolverWithTimeZone.resolve() wraps every failure while computing the next run date of a cron expression in a FlowableException with this message. It means the timer/duedate description (cron expression plus optional timezone) could not be parsed or evaluated, and the original cause (often a ParseException from CronExpression) is chained. This is a configuration/definition problem, not a transient runtime fault.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/AdvancedSchedulerResolverWithTimeZone.java:46

public class AdvancedSchedulerResolverWithTimeZone implements AdvancedSchedulerResolver {

    @Override
    public Date resolve(String duedateDescription, ClockReader clockReader, TimeZone timeZone) {
        Calendar nextRun = null;

        try {
            if (duedateDescription.startsWith("R")) {
                nextRun = new DurationHelper(duedateDescription, clockReader).getCalendarAfter(clockReader.getCurrentCalendar(timeZone));
            } else {
                CronExpression cronExpression = new CronExpression(duedateDescription, clockReader);
                cronExpression.setTimeZone(timeZone);
                Date nextRunDate = cronExpression.getTimeAfter(clockReader.getCurrentCalendar(timeZone).getTime());
                nextRun = new GregorianCalendar();
                nextRun.setTime(nextRunDate);
            }

        } catch (Exception e) {
            throw new FlowableException("Failed to parse scheduler expression: " + duedateDescription, e);
        }

        return nextRun == null ? null : nextRun.getTime();
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Print/inspect the chained cause (e.getCause()) to get the exact ParseException from CronExpression and fix the cron string
  2. Validate the expression with a cron validator (or construct a CronExpression directly in a unit test) before deploying the process definition
  3. Ensure the expression has at least 6 fields (second minute hour day-of-month month day-of-week, optional year) and leaves either day-of-month or day-of-week as '?'
  4. If the duedate is meant to be a duration (e.g. PT10M) not a cron, do not pass it to the cron-based resolver

Example fix

// before
String duedate = "0 0 12 ? * MON,FRI-L"; // invalid: L mixed with list in day-of-week
resolver.resolve(duedate, timeZone, clockReader);
// after
String duedate = "0 0 12 ? * MON,FRI"; // valid expression
resolver.resolve(duedate, timeZone, clockReader);
Defensive patterns

Strategy: try-catch

Validate before calling

public static void validateCron(String expr) {
    try { new CronExpression(expr, new DefaultClockReader()); }
    catch (Exception e) { throw new IllegalArgumentException("Invalid cron: " + expr, e); }
}

Type guard

boolean isUsableCron(String s) { return s != null && s.trim().split("\\s+").length >= 6; }

Try / catch

try {
    Date next = resolver.resolve(duedate, timeZone, clockReader);
} catch (FlowableException e) {
    logger.error("Bad schedule definition '" + duedate + "'", e.getCause());
    throw new ConfigurationException("Fix timer definition: " + duedate, e);
}

Prevention

When it happens

Trigger: Calling resolve(duedateDescription, timeZone, clockReader) with a malformed cron expression string, an expression that CronExpression rejects (bad 'L'/'#' usage, too few fields, invalid month/day names), or a description that fails CronExpression construction/evaluation inside the try block.

Common situations: Timer event definitions in BPMN XML with hand-written cron strings; admin-entered job/timer definitions; expressions copied from Quartz v1 docs that use unsupported combinations (e.g. both day-of-month and day-of-week restricted); typos in month/day names; missing cron fields after refactoring.

Understand the failure class

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/ba9fb6200c3bdcbd. Report an issue: GitHub.