flowable/flowable-engine · error · ParseException
Illegal cron expression format (
Error message
Illegal cron expression format (
What it means
buildExpression catches any non-ParseException thrown while parsing/storing field values (NumberFormatException, StringIndexOutOfBoundsException, etc.) and rethrows it as a ParseException 'Illegal cron expression format (<exception>)'. It is the generic fallback for structurally broken expressions not caught by the specific checks.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:540
TreeSet<Integer> dow = getSet(DAY_OF_WEEK);
TreeSet<Integer> dom = getSet(DAY_OF_MONTH);
// Copying the logic from the UnsupportedOperationException below
boolean dayOfMSpec = !dom.contains(NO_SPEC);
boolean dayOfWSpec = !dow.contains(NO_SPEC);
if (!dayOfMSpec || dayOfWSpec) {
if (!dayOfWSpec || dayOfMSpec) {
throw new ParseException(
"Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.",
0);
}
}
} catch (ParseException pe) {
throw pe;
} catch (Exception e) {
throw new ParseException("Illegal cron expression format (" + e + ")", 0);
}
}
protected int storeExpressionVals(int pos, String s, int type) throws ParseException {
int incr = 0;
int i = skipWhiteSpace(pos, s);
if (i >= s.length()) {
return i;
}
char c = s.charAt(i);
if ((c >= 'A') && (c <= 'Z') && !"L".equals(s) && !"LW".equals(s) && !s.matches("^L-[0-9]*[W]?")) {
String sub = s.substring(i, i + 3);
int sval = -1;
int eval = -1;
if (type == MONTH) {
sval = getMonthNumber(sub) + 1;
if (sval <= 0) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Read the parenthesized cause in the message to identify the exact malformed token and fix it
- Validate the expression offline (construct CronExpression in a test or use a cron validator) before deployment
- Check for empty/whitespace fragments when the cron is built from templates or variables
- Ensure numeric fields stay within range (seconds/minutes 0-59, hours 0-23, days 1-31, months 1-12/JAN-DEC, days-of-week 1-7/SUN-SAT)
Example fix
// before
String cron = "0 0 " + hour + " * * ?"; // hour may be "" or "abc"
// after
int h = Integer.parseInt(hour); // throws NumberFormatException early, and:
if (h < 0 || h > 23) throw new IllegalArgumentException("hour out of range: " + h);
String cron = "0 0 " + h + " * * ?"; Defensive patterns
Strategy: validation
Validate before calling
// ranges and values per field
int[][] limits = {{0,59},{0,59},{0,23},{1,31},{1,12},{1,7}};
// validate each numeric token of field i against limits[i] before constructing CronExpression Try / catch
try { new CronExpression(expr, clockReader); }
catch (ParseException e) { if (e.getMessage().startsWith("Illegal cron expression format")) { log.error("Structurally broken cron: {}", expr, e); } throw e; } Prevention
- Check numeric ranges: sec/min 0-59, hour 0-23, dom 1-31, month 1-12, dow 1-7
- Avoid template substitution that can inject empty strings into cron fields
- Reject stray characters (repeated '/', '-', missing operands) with a regex pre-check
- Test every cron string in CI with new CronExpression(...)
When it happens
Trigger: new CronExpression(expr, clockReader) with garbage fields that make storeExpressionVals throw — non-numeric tokens like '0 0 abc * *', out-of-range numbers, stray characters such as '0 0 12 */ * ?', truncated ranges like '0 0 5- * ?'.
Common situations: Hand-edited BPMN timer XML with typos; values substituted into cron strings (template injection of empty or invalid fragments); locale/paste issues introducing invisible characters.
Related errors
- Unexpected end of expression.
- Support for specifying both a day-of-week AND a day-of-month
- Invalid Month value: '
- Failed to parse scheduler expression:
- cronExpression cannot be null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/0a3276e39d9206be.
Report an issue: GitHub.