alibaba/spring-cloud-alibaba · error · ParseException
Support for specifying 'L' and 'LW' with other days of the…
Error message
Support for specifying 'L' and 'LW' with other days of the month is not implemented
What it means
Thrown during CronExpression.buildExpression while parsing the DAY_OF_MONTH field: if the token contains 'L' (last day / last weekday 'LW'), is longer than one char, and also contains a comma (a list of days), the parser refuses it with ParseException. Quartz does not implement combining the 'L'/'LW' modifier with other comma-separated day values.
Solutions
- Split into two jobs/triggers: one for the fixed days (e.g. '0 0 0 15 * ?') and one for the last day ('0 0 0 L * ?').
- If you only need the last day, use 'L' alone; if the last weekday, use 'LW' alone — without a comma list.
- Validate the cron with the same CronExpression class at config-load time to catch it before deployment.
Example fix
# before (invalid: L mixed with list) 0 0 0 15,L * ? # after (two separate triggers) 0 0 0 15 * ? # the 15th 0 0 0 L * ? # the last day of month
Defensive patterns
Strategy: try-catch
Validate before calling
static String validateCron(String cron) throws ParseException {
// trial-parse at config/validation time
new com.alibaba.cloud.scheduling.schedulerx.util.CronExpression(cron);
return cron;
} Type guard
// reject day-of-month lists containing L/LW before parsing
static boolean isValidDom(String dom) {
boolean hasL = dom.indexOf('L') != -1;
return !(hasL && dom.length() > 1 && dom.contains(","));
} Try / catch
try {
CronExpression expr = new CronExpression(cron);
} catch (ParseException e) {
// e.g. "Support for specifying 'L' and 'LW' with other days of the month is not implemented"
throw new IllegalArgumentException("Invalid cron '" + cron + "': " + e.getMessage(), e);
} Prevention
- Never combine 'L'/'LW' with comma-separated days in one field; use multiple triggers.
- Add a startup cron-validation step that trial-parses every configured cron.
When it happens
Trigger: A cron whose day-of-month field is a list including L or LW, e.g. '0 0 0 15,L * ?' or '0 0 0 1,LW * ?'. The check at CronExpression.java:270-272 matches DAY_OF_MONTH && indexOf('L')!=-1 && length()>1 && contains(',').
Common situations: Wanting 'every 15th and the last day of the month' and writing '15,L'; copy-pasting a Unix-style cron (5-field) into the 6/7-field Quartz format and appending a stray list; misunderstanding that L cannot be mixed in a list.
Related errors
- '?' can only be specfied for Day-of-Month -OR- Day-of-Week.
- '?' can only be specfied for Day-of-Month or Day-of-Week.
- Illegal character after '?
- Illegal characters for this position
- Illegal cron expression format
AI-assisted analysis of alibaba/spring-cloud-alibaba@115d590110 (2026-08-14).
Data as JSON: /api/errors/90a104466ea2cb34.
Report an issue: GitHub.
Appendix: source
Thrown at spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java:271
seconds = new TreeSet<>();
minutes = new TreeSet<>();
hours = new TreeSet<>();
daysOfMonth = new TreeSet<>();
months = new TreeSet<>();
daysOfWeek = new TreeSet<>();
years = new TreeSet<>();
int exprOn = SECOND;
final StringTokenizer exprsTok = new StringTokenizer(expression, " \t",
false);
while (exprsTok.hasMoreTokens() && exprOn <= YEAR) {
final String expr = exprsTok.nextToken().trim();
// throw an exception if L is used with other days of the month
if (exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) {
throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1);
}
// 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);
}
final StringTokenizer vTok = new StringTokenizer(expr, ",");
while (vTok.hasMoreTokens()) {
final String v = vTok.nextToken();
storeExpressionVals(0, v, exprOn);
}
exprOn++;
}
View on GitHub (pinned to 115d590110)