jeecgboot/JeecgBoot · error · ParseException

Support for specifying multiple "nth" days is not implemente

Error message

Support for specifying multiple "nth" days is not implemented.

What it means

Thrown by CronExpression's parser when the day-of-week field contains more than one '#' character — e.g., 'FRI#2,FRI#4' or '6#1,6#3'. The '#' modifier specifies the 'nth occurrence' of a day in a month (e.g., '6#3' = third Friday). Quartz does not support multiple nth-day specifiers in a single expression. The check detects a second '#' after the first one in the field.

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:494

            int exprOn = SECOND;

            StringTokenizer exprsTok = new StringTokenizer(expression, " \t",
                    false);

            if(exprsTok.countTokens() > 7) {
                throw new ParseException("Invalid expression has too many terms: " + expression, -1);
            }

            while (exprsTok.hasMoreTokens() && exprOn <= YEAR) {
                String expr = exprsTok.nextToken().trim();

                // throw an exception if L is used with other days of the week
                if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1  && expr.contains(",")) {
                    throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1);
                }
                if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) {
                    throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1);
                }

                StringTokenizer vTok = new StringTokenizer(expr, ",");
                while (vTok.hasMoreTokens()) {
                    String v = vTok.nextToken();
                    storeExpressionVals(0, v, exprOn);
                }

                exprOn++;
            }

            if (exprOn <= DAY_OF_WEEK) {
                throw new ParseException("Unexpected end of expression.",
                        expression.length());
            }

            if (exprOn <= YEAR) {
                storeExpressionVals(0, "*", YEAR);

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Split into multiple CronTriggers: one for '6#1' (first Friday) and another for '6#3' (third Friday), both targeting the same job.
  2. If the schedule can be expressed as 'every N weeks', consider using a different scheduling strategy (e.g., a simple periodic trigger with date filtering).
  3. Use '6#1' alone if only one nth-occurrence is needed: '0 0 12 ? * 6#1'.

Example fix

// before: multiple # specifiers in one expression — invalid
String cron = "0 0 12 ? * 6#1,6#3";
CronExpression expr = new CronExpression(cron);

// after: two separate triggers
CronTrigger firstFriday = TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 ? * 6#1"))
    .build();
CronTrigger thirdFriday = TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 ? * 6#3"))
    .build();
scheduler.scheduleJob(jobDetail, firstFriday);
scheduler.scheduleJob(jobDetail, thirdFriday);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate day-of-week field for multiple # specifiers
public void validateDayOfWeekField(String cronExpression) {
    String[] fields = cronExpression.trim().split("\\s+");
    if (fields.length >= 6) {
        String dayOfWeek = fields[5];
        int hashCount = dayOfWeek.length() - dayOfWeek.replace("#", "").length();
        if (hashCount > 1) {
            throw new IllegalArgumentException(
                "Cannot specify multiple '#' nth-day modifiers: " + dayOfWeek);
        }
    }
}

Type guard

// Check if day-of-week field has at most one # specifier
public boolean hasValidNthDaySpecifier(String dow) {
    if (dow == null || dow.isEmpty()) return true;
    int hashCount = dow.length() - dow.replace("#", "").length();
    return hashCount <= 1;
}

Try / catch

try {
    CronExpression cron = new CronExpression(expression);
} catch (ParseException e) {
    if (e.getMessage().contains("nth")) {
        throw new IllegalArgumentException(
            "Multiple '#' specifiers are not supported. Split into separate triggers.", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Cron expression like '0 0 12 ? * 6#1,6#3' trying to run on the first and third Friday of each month. Expression like '0 0 6 ? * 1#1,1#3' for first and third Sunday. Any comma-separated day-of-week value containing two or more '#' characters.

Common situations: Scheduling bi-weekly or specific-week-of-month jobs that need multiple nth-occurrence rules. Misunderstanding that '#' can only appear once per expression. Building dynamic cron strings that concatenate multiple '#'-based rules.

Related errors


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