flowable/flowable-engine · error · ParseException
'W' option is not valid here. (pos=
Error message
'W' option is not valid here. (pos=
What it means
Parse-time guard in CronExpression.checkNext: the 'W' (nearest weekday) option was used in a field other than day-of-month (it is only valid there), so the expression is rejected at the given position.
Solutions
- Use 'nW' only in the day-of-month field, e.g. "0 0 0 15W * ?"
- For nearest-weekday-like behavior in day-of-week, pick an explicit weekday value instead
- Remove the 'W' from unsupported fields
Example fix
// before
new CronExpression("0 0 0 ? * 5W");
// after
new CronExpression("0 0 0 15W * ?"); // nearest weekday to the 15th Defensive patterns
Strategy: validation
Validate before calling
boolean validWOption(String[] fields) {
return fields[3] != null && fields[3].matches("\\d{1,2}W");
} Try / catch
try {
CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
if (e.getMessage().startsWith("'W' option is not valid here")) {
throw new ConfigurationException("'W' is only valid as nW in day-of-month: " + expr, e);
}
throw e;
} Prevention
- Use nW only in the day-of-month field
- Use explicit weekday values instead of W when weekday-field behavior is desired
- Document the supported Quartz option characters for whoever writes cron strings
When it happens
Trigger: Expressions like "0 0 0 ? * 5W" (W in day-of-week) or "0 0 0 15W * ?" reached via checkNext after hour fields; 'W' appended to month or weekday values.
Common situations: Confusing 'W' semantics across cron dialects (some Unix crons reject W entirely; Quartz/Flowable only allow it in day-of-month); typos.
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
- 'L' option is not valid here. (pos=
- The 'W' option does not make sense with values larger than…
- Unexpected character:
- 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/13db37e7d63e8101.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:754
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);
}
TreeSet<Integer> set = getSet(type);
set.add(val);
i++;
return i;
}
if (c == '#') {
if (type != DAY_OF_WEEK) {
throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i);
}
i++;
try {View on GitHub (pinned to d6d39ce1c6)