Activiti/Activiti · error · ParseException
The 'W' option does not make sense with values larger than…
Error message
The 'W' option does not make sense with values larger than 31 (max number of days in a month)
What it means
This library's cron parser (a port of Quartz's CronExpression) supports the 'W' suffix on a day-of-month field, meaning 'nearest weekday to the given day'. The value preceding 'W' must be a valid day of a month. Since no month has more than 31 days, any value above 31 is rejected at parse time with a ParseException.
Solutions
- Correct the day-of-month value before 'W' to a number between 1 and 31.
- If the intent was 'last day of the month', use 'L' instead of an over-large 'W' value.
- Validate the cron string (or bound the user-supplied day value to 1..31) before constructing the CronExpression.
Example fix
// before String cron = "0 0 0 45W * ?"; CronExpression ce = new CronExpression(cron); // after String cron = "0 0 0 15W * ?"; // 15W: nearest weekday to the 15th CronExpression ce = new CronExpression(cron);
Defensive patterns
Strategy: validation
Validate before calling
int dayVal = extractDayOfMonthBeforeW(cron); // parse token yourself
if (dayVal > 31) throw new IllegalArgumentException("'W' day-of-month must be 1-31"); Type guard
boolean isValidWeekdaySpec(String token) {
int i = token.indexOf('W');
if (i < 1) return true;
try { return Integer.parseInt(token.substring(0, i)) <= 31; }
catch (NumberFormatException e) { return false; }
} Try / catch
try {
CronExpression ce = new CronExpression(cron);
} catch (ParseException e) {
if (e.getMessage().contains("'W' option")) {
throw new ConfigurationException("Invalid day-of-month 'W' value in cron: " + cron, e);
}
throw e;
} Prevention
- Never build 'W' expressions from unbounded user input; clamp to 1-31.
- Use 'L' for last-day-of-month semantics instead of guessing large 'W' values.
- Validate cron strings at configuration load time, not at scheduling time.
When it happens
Trigger: Parsing a cron expression whose DAY_OF_MONTH token ends with 'W' and has a numeric value greater than 31 (e.g. '0 0 0 45W * ?' or '0 0 0 32W * ?'), via storeExpressionVals during CronExpression construction.
Common situations: Typo or hand-edited cron string in a timer boundary event or job definition in an Activiti BPMN process; a generated expression built from user input without range validation; copy-paste from another scheduler dialect with different day-of-month semantics.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- '#' option is not valid here. (pos=)
- Start year must be less than stop year
- Unexpected character:
- Unexpected character '' after '/'
- Day of month values must be between 1 and 31
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/9f5c8fb4435849c4.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/calendar/CronExpression.java:581
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(Integer.valueOf(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(Integer.valueOf(val));
i++;
return i;
}
if (c == '#') {
if (type != DAY_OF_WEEK) {
throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i);
}
i++;
try {
nthdayOfWeek = Integer.parseInt(s.substring(i));
if (nthdayOfWeek < 1 || nthdayOfWeek > 5) {
throw new Exception();View on GitHub (pinned to 56435b1a97)