jeecgboot/JeecgBoot · error · ParseException

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

Error message

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

What it means

Thrown when the '#' (nth occurrence) modifier appears in any cron field other than day-of-week. The '#' syntax (e.g., '6#3' = 3rd Friday) is exclusively a day-of-week feature. Its presence in any other field is a parse error.

Source

Thrown at jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/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 96fb33f5ec)

Solutions

  1. Ensure '#' appears only in the day-of-week field (the 6th field in a 6-field expression, or 7th if year is included).
  2. Use '?' in the day-of-month field when using '#' in day-of-week.
  3. Verify the full field order: seconds minutes hours day-of-month month day-of-week.

Example fix

// before
String cron = "0 0 0 5#3 * ?";  // '#' is in day-of-month — wrong
// after
String cron = "0 0 0 ? * 6#3";  // '#' in day-of-week = 3rd Friday
Defensive patterns

Strategy: validation

Validate before calling

// Ensure '#' only appears in the day-of-week field (field index 5)
String[] fields = cronExpr.split("\\s+");
for (int f = 0; f < fields.length; f++) {
    if (fields[f].contains("#") && f != 5) {
        throw new IllegalArgumentException("'#' is only valid in day-of-week field");
    }
}

Type guard

boolean isHashOnlyInDayOfWeek(String cron) {
    String[] fields = cron.trim().split("\\s+");
    for (int f = 0; f < fields.length; f++) {
        if (fields[f].contains("#") && f != 5) return false;
    }
    return true;
}

Try / catch

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

Prevention

When it happens

Trigger: A cron expression containing '#' after a numeric value where type != DAY_OF_WEEK — e.g., day-of-month field '15#1', hour field '10#2', or minute field '0#1'.

Common situations: Field misalignment (extra/missing field shifts '#' into the wrong position); developer confuses day-of-month and day-of-week; copy-paste from documentation without adjusting field order.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/f114496fab0d1532. Report an issue: GitHub.