jeecgboot/JeecgBoot · error · ParseException
Support for specifying multiple "nth" days is not…
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.
Solutions
- Split into multiple CronTriggers: one for '6#1' (first Friday) and another for '6#3' (third Friday), both targeting the same job.
- 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).
- 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
- Use at most one '#' specifier per cron expression (e.g., '6#3' for third Friday only).
- For multiple nth-occurrence rules (e.g., first AND third Friday), create separate triggers.
- Validate cron expressions in the admin UI before saving to prevent runtime parse errors.
- Educate users on Quartz '#' modifier semantics: dayOfWeek#nthOccurrence.
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
- Support for specifying both a day-of-week AND a…
- Support for specifying 'L' with other days of the week is…
- Invalid expression has too many terms
- Unexpected end of expression.
- A numeric value between 1 and 5 must follow the '#' option
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/19b28160d769320e.
Report an issue: GitHub.
Appendix: 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)