xuxueli/xxl-job · error · ParseException
'W' option is not valid here. (pos={})
Error message
'W' option is not valid here. (pos={}) What it means
In checkNext, the 'W' (nearest weekday) modifier following a numeric value is only valid in the Day-of-Month field. 'W' means 'the nearest weekday to day N of the month'. This error fires when 'W' appears after a number in any field other than day-of-month (e.g., day-of-week, hour, etc.).
Source
Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:769
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) {
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();
}View on GitHub (pinned to e74c784f68)
Solutions
- Move the 'W' modifier and its preceding number to the day-of-month field: '0 0 0 15W * ?'.
- If a weekday-based schedule is needed in day-of-week, use the appropriate day-of-week syntax (e.g., 'MON-FRI' or '1-5').
- Confirm the field position matches Quartz's 6 or 7 field layout.
Example fix
// before "0 0 0 ? * 5W" // after "0 0 0 5W * ?"
Defensive patterns
Strategy: validation
Validate before calling
// 'NW' (number followed by W) is only valid in day-of-month (field index 3)
String[] parts = cron.trim().split("\\s+");
for (int idx = 0; idx < parts.length; idx++) {
if (parts[idx].matches(".*\\d+W.*") && idx != 3) {
throw new IllegalArgumentException("'NW' is only valid in day-of-month (field 3): " + parts[idx]);
}
} Type guard
boolean isNumberWInDayOfMonthOnly(String[] parts) {
for (int idx = 0; idx < parts.length; idx++) {
if (parts[idx].matches(".*\\d+W.*") && idx != 3) return false;
}
return true; Try / catch
try {
new CronExpression(cron);
} catch (ParseException e) {
if (e.getMessage().contains("'W' option is not valid here")) {
// move 'NW' to the day-of-month field
}
} Prevention
- The 'W' (nearest weekday) modifier is day-of-month only.
- For weekday-only schedules in day-of-week, use a range like '1-5' or 'MON-FRI'.
- Verify field positions match the Quartz layout before submitting.
When it happens
Trigger: A cron expression like '0 0 0 ? * 5W' where '5W' appears in the day-of-week field. The parser reads 5 as a digit, enters checkNext, finds 'W', and since type != DAY_OF_MONTH, throws at line 769.
Common situations: Placing the 'W' modifier in the wrong field, or misunderstanding that 'W' is a day-of-month-only feature.
Related errors
- Offset from last day must be <= {}
- The 'W' option does not make sense with values larger than 3
- '?' 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/52e679d35a0ab43c.
Report an issue: GitHub.