xuxueli/xxl-job · error · ParseException

'#' option is not valid here. (pos={})

Error message

'#' option is not valid here. (pos={})

What it means

In checkNext, the '#' (nth occurrence) modifier following a numeric value is only valid in the Day-of-Week field. '#N' means 'the Nth occurrence of the given weekday in the month'. This error fires when '#' appears after a number in any field other than day-of-week.

Source

Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:780

            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",
                        i);
            }

            TreeSet<Integer> set = getSet(type);
            set.add(val);
            i++;
            return i;
        }

View on GitHub (pinned to e74c784f68)

Solutions

  1. Move the '#N' modifier and its preceding weekday number to the day-of-week field: '0 0 0 ? * 5#1'.
  2. Ensure day-of-month uses '?' or '*' when day-of-week uses '#'.
  3. Verify the field position in the 6 or 7 field layout.

Example fix

// before
"0 0 0 5#1 * ?"
// after
"0 0 0 ? * 5#1"
Defensive patterns

Strategy: validation

Validate before calling

// 'N#M' is only valid in day-of-week (field index 5)
String[] parts = cron.trim().split("\\s+");
for (int idx = 0; idx < parts.length; idx++) {
    if (parts[idx].contains("#") && idx != 5) {
        throw new IllegalArgumentException("'#' is only valid in day-of-week (field 5): " + parts[idx]);
    }
}

Type guard

boolean isHashInDayOfWeekOnly(String[] parts) {
    for (int idx = 0; idx < parts.length; idx++) {
        if (parts[idx].contains("#") && idx != 5) return false;
    }
    return true;

Try / catch

try {
    new CronExpression(cron);
} catch (ParseException e) {
    if (e.getMessage().contains("'#' option is not valid here")) {
        // move the '#N' expression to the day-of-week field
    }
}

Prevention

When it happens

Trigger: A cron expression like '0 0 0 5#1 * ?' where '5#1' appears in the day-of-month field. The parser reads 5 as a digit, enters checkNext, finds '#', and since type != DAY_OF_WEEK, throws at line 780.

Common situations: Placing the '#' modifier in the wrong field, or misunderstanding that '#' is a day-of-week-only feature meaning 'Nth weekday of the month'.

Related errors


AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14). Data as JSON: /api/errors/724539371d072625. Report an issue: GitHub.