jeecgboot/JeecgBoot · error · ParseException

Support for specifying 'L' with other days of the week is no

Error message

Support for specifying 'L' with other days of the week is not implemented

What it means

Thrown by CronExpression's parser when the day-of-week field contains 'L' (last weekday of month) combined with other days using commas — e.g., 'FRI,L' or '1,L'. Quartz supports 'L' as a standalone modifier meaning 'last <day> of the month' (e.g., '6L' = last Friday), but mixing it with additional days in a comma-separated list is not implemented. This is a parser-level limitation, not a configurable behavior.

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

            if (years == null) {
                years = new TreeSet<>();
            }

            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());
            }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Split the schedule into multiple triggers/jobs: one for the recurring days and a separate one for the 'L' (last weekday) rule.
  2. If you need 'last Friday of every month', use '6L' alone in the day-of-week field: '0 0 12 ? * 6L'.
  3. If you need every Monday, use 'MON' or '2' alone: '0 0 12 ? * 2'.
  4. Combine multiple CronTriggers in the scheduler for the same job rather than trying to express everything in one cron string.

Example fix

// before: invalid — mixing L with other days
String cron = "0 0 12 ? * 2,6L"; // Monday + last Friday
CronExpression expr = new CronExpression(cron);

// after: use two separate triggers for the same job
// Trigger 1: every Monday
CronTrigger monday = TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 ? * 2"))
    .build();
// Trigger 2: last Friday of month
CronTrigger lastFriday = TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 ? * 6L"))
    .build();
scheduler.scheduleJob(jobDetail, monday);
scheduler.scheduleJob(jobDetail, lastFriday);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate day-of-week field for L+comma conflict
public void validateDayOfWeekField(String cronExpression) {
    String[] fields = cronExpression.trim().split("\\s+");
    if (fields.length >= 6) {
        String dayOfWeek = fields[5];
        if (dayOfWeek.contains("L") && dayOfWeek.contains(",")) {
            throw new IllegalArgumentException(
                "Cannot combine 'L' with other days in day-of-week: " + dayOfWeek);
        }
    }
}

Type guard

// Check if day-of-week field is valid for Quartz
public boolean isValidDayOfWeek(String dow) {
    if (dow == null || dow.isEmpty()) return false;
    if (dow.contains("L") && dow.contains(",")) return false;
    return true;
}

Try / catch

try {
    CronExpression cron = new CronExpression(expression);
} catch (ParseException e) {
    if (e.getMessage().contains("'L' with other days")) {
        // Suggest splitting into multiple triggers
        throw new IllegalArgumentException(
            "Cannot combine 'L' with comma-separated days. Use separate triggers for each rule.", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Cron expression with day-of-week field like 'MON,TUE,L' or '1,2,L' intending 'Mondays, Tuesdays, and last day-of-week of month'. Expression like '6L,FRI' trying to say 'last Friday and every Friday'. Using 'L' as shorthand for 'last day of any week' combined with specific days.

Common situations: Writing complex scheduling rules that need both recurring weekdays and the last occurrence of a weekday. Misunderstanding 'L' semantics — thinking it means 'last day of month' generically rather than modifying the specific day it's attached to. Attempting to combine end-of-month logic with regular weekly schedules in a single expression.

Related errors


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