flowable/flowable-engine · error · ParseException
'L' option is not valid here. (pos=
Error message
'L' option is not valid here. (pos=
What it means
checkNext throws this when the 'L' (last-day) option character appears after a value in a field that is not DAY_OF_WEEK. 'L' is only valid as 'nL' in day-of-week, or alone in day-of-month (handled elsewhere in storeExpressionVals).
Solutions
- Use 'L' alone only in the day-of-month field: "0 0 0 L * ?"
- Use 'nL' only in the day-of-week field: "0 0 0 ? * 6L" (last Friday)
- Remove the stray 'L' from fields that do not support it
Example fix
// before
new CronExpression("0 0 0L * * ?");
// after
new CronExpression("0 0 0 L * ?"); // last day of month Defensive patterns
Strategy: validation
Validate before calling
boolean validLOption(String[] fields) {
// fields in Quartz order: sec min hour dom mon dow [year]
boolean domL = fields[3].equals("L") || fields[3].equals("LW") || fields[3].matches("\\d+W");
boolean dowL = fields[5].matches("[1-7]L|[A-Z]{3}L");
return fields[0].matches("[0-9*/,-]+") && fields[1].matches("[0-9*/,-]+")
&& fields[2].matches("[0-9*/,-]+") && (fields[3].matches("[0-9*?/,-]+") || domL)
&& fields[4].matches("[A-Z0-9*?/,-]+") && (fields[5].matches("[0-9?*/,-]+|[A-Z?,/-]+") || dowL);
} Try / catch
try {
CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
if (e.getMessage().startsWith("'L' option is not valid here")) {
throw new ConfigurationException("'L' is only valid alone in day-of-month or as nL in day-of-week: " + expr, e);
}
throw e;
} Prevention
- Remember: L alone -> day-of-month; nL -> day-of-week; LW -> last weekday of month
- Do not put L in sec/min/hour/month/year fields
- Validate expressions in tests before deployment
When it happens
Trigger: Expressions using 'L' in wrong fields, e.g. "0 0 0L * * ?" (L after hour values), "0 0 L 1 * ?" reached through checkNext, or 'L' appended to month/second/minute values.
Common situations: Misunderstanding Quartz 'L' semantics; copy-pasting expressions from documentation for other cron dialects; typos where 'L' was meant for the day-of-month field.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Day-of-Week values must be between 1 and 7
- Unexpected character:
- 'W' option is not valid here. (pos=
- A numeric value between 1 and 5 must follow the '#' option
- '?' can only be specified for Day-of-Month -OR- Day-of-Week.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/bbda159a649e03e1.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:742
int end = -1;
int i = pos;
if (i >= s.length()) {
addToSet(val, end, -1, type);
return i;
}
char c = s.charAt(pos);
if (c == 'L') {
if (type == DAY_OF_WEEK) {
if (val < 1 || val > 7) {
throw new ParseException("Day-of-Week values must be between 1 and 7", -1);
}
lastdayOfWeek = true;
} else {
throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i);
}
TreeSet<Integer> set = getSet(type);
set.add(val);
i++;
return i;
}
if (c == 'W') {
if (type == DAY_OF_MONTH) {
nearestWeekday = true;
} else {
throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i);
}
if (val > 31) {
throw new ParseException(
"The 'W' option does not make sense with values larger than 31 (max number of days in a month)",
i);
}View on GitHub (pinned to d6d39ce1c6)