xuxueli/xxl-job · error · ParseException
The 'W' option does not make sense with values larger than 3
Error message
The 'W' option does not make sense with values larger than 31 (max number of days in a month)
What it means
In checkNext, the 'W' (nearest weekday) modifier in the Day-of-Month field requires the preceding numeric value to be 31 or less, since no month has more than 31 days. This error fires when val > 31.
Source
Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:772
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) {
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);
nearestWeekdays.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 {
nthDayOfWeek = Integer.parseInt(s.substring(i));
if (nthDayOfWeek < 1 || nthDayOfWeek > 5) {
throw new Exception();
}
} catch (Exception e) {
throw new ParseException(
"A numeric value between 1 and 5 must follow the '#' option",View on GitHub (pinned to e74c784f68)
Solutions
- Reduce the day-of-month value to 31 or less before 'W'.
- Validate the value against the 1-31 range before constructing the expression.
- If the intent is the last weekday of the month, use 'LW' instead of a large number.
Example fix
// before "0 0 0 32W * ?" // after "0 0 0 15W * ?"
Defensive patterns
Strategy: validation
Validate before calling
// Check 'NW' value in day-of-month (field index 3) is <= 31
String[] parts = cron.trim().split("\\s+");
if (parts.length > 3 && parts[3].matches(".*\\d+W.*")) {
String numPart = parts[3].replaceAll("W.*", "").replaceAll(".*[^0-9]", "");
if (!numPart.isEmpty()) {
int val = Integer.parseInt(numPart);
if (val > 31) throw new IllegalArgumentException("'W' value must be <= 31: " + val);
}
} Type guard
boolean isValidNearestWeekdayValue(String domField) {
if (!domField.contains("W")) return true;
String num = domField.replaceAll("W.*", "").replaceAll(".*[^0-9]", "");
if (num.isEmpty()) return true;
return Integer.parseInt(num) <= 31; Try / catch
try {
new CronExpression(cron);
} catch (ParseException e) {
if (e.getMessage().contains("'W' option does not make sense")) {
// reduce the day value to 31 or less, or use 'LW' for last weekday
}
} Prevention
- Clamp 'NW' values to 1-31 before building the expression.
- For 'last weekday of the month', use 'LW' instead of a large number.
- Validate day-of-month values against 1-31 in your cron builder.
When it happens
Trigger: A cron expression like '0 0 0 32W * ?' where the value before 'W' in the day-of-month field exceeds 31. The check at line 771 tests val > 31.
Common situations: Generating a day-of-month value dynamically without clamping, or a typo/overflow producing a value beyond 31.
Related errors
- Offset from last day must be <= {}
- 'W' option is not valid here. (pos={})
- '?' can only be specified for Day-of-Month -OR- Day-of-Week.
- 'L' not expected in seconds, minutes or hours fields.
- Day-of-Week values must be between 1 and 7
AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14).
Data as JSON: /api/errors/e66d697eed5155a1.
Report an issue: GitHub.