jeecgboot/JeecgBoot · error · ParseException
'L' option is not valid here. (pos=${i})
Error message
'L' option is not valid here. (pos=${i}) What it means
Thrown when the 'L' (last) character appears in a cron field that is not day-of-week. In this particular CronExpression implementation, 'L' is only implemented for DAY_OF_WEEK within this code path — using it in any other field type (second, minute, hour, day-of-month, month) triggers the error. Note that standard Quartz also allows 'L' for day-of-month, but this fork's parser does not handle that here.
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:759
throws ParseException {
int end = -1;
int i = pos;
if (i >= s.length()) {
addToSet(val, end, -1, type);
return i;
}
char c = s.charAt(pos);
if (c == 'L') {
if (type == DAY_OF_WEEK) {
if(val < 1 || val > 7)
throw new ParseException("Day-of-Week values must be between 1 and 7", -1);
lastDayOfWeek = true;
} else {
throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i);
}
TreeSet<Integer> set = getSet(type);
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;
}
View on GitHub (pinned to 96fb33f5ec)
Solutions
- Move the 'L' modifier to the day-of-week field only (e.g., '0 0 0 ? * 5L' for last Friday).
- For 'last day of month' semantics, check whether this fork's buildTime logic supports 'L' in the day-of-month field via a different code path; if not, use a workaround with '?' in DOW and explicit last-day handling.
- Replace the expression with one that uses only supported syntax for the target field.
Example fix
// before String cron = "0 0 0 L * ?"; // 'L' in day-of-month — not supported here // after String cron = "0 0 0 ? * 7L"; // 'L' only in day-of-week (last Saturday)
Defensive patterns
Strategy: validation
Validate before calling
// Ensure 'L' only appears in the day-of-week field
String[] fields = cronExpr.split("\\s+");
// fields[5] is day-of-week (6-field expression)
for (int f = 0; f < fields.length; f++) {
if (fields[f].contains("L") && f != 5) {
throw new IllegalArgumentException("'L' is only valid in day-of-week field");
}
} Type guard
boolean isLOnlyInDayOfWeek(String cron) {
String[] fields = cron.trim().split("\\s+");
for (int f = 0; f < fields.length; f++) {
if (fields[f].contains("L") && f != 5) return false;
}
return true;
} Try / catch
try {
CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
if (e.getMessage().contains("'L' option is not valid here")) {
// inform user 'L' must be in day-of-week field
}
throw e;
} Prevention
- Remember the field order: sec min hr DOM month DOW [year].
- Only place 'L' in the DOW field in this implementation.
- Use a cron expression linter/validator in the UI before saving.
When it happens
Trigger: A cron expression where 'L' appears after a numeric value in any field except day-of-week — e.g., day-of-month field '15L', hour field '8L', or minute field '0L'. The parser reads the value, then encounters 'L' as the next character with type != DAY_OF_WEEK.
Common situations: Developer expects 'L' to work for day-of-month ('0 0 0 L * ?') as it does in upstream Quartz but this fork doesn't support it in this branch; copy-paste from a Quartz reference that documents 'L' for day-of-month.
Related errors
- Day-of-Week values must be between 1 and 7
- 'W' option is not valid here. (pos=${i})
- The 'W' option does not make sense with values larger than 3
- '#' option is not valid here. (pos=${i})
- Unexpected character '${c}' after '/'
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/261969a871c2fba5.
Report an issue: GitHub.