Activiti/Activiti · error · ParseException
'L' option is not valid here. (pos=)
Error message
'L' option is not valid here. (pos=)
What it means
checkNext throws this ParseException when the 'L' special character is used in a cron field other than day-of-week. The 'L' option is only legal as a suffix on the day-of-week field (e.g. '5L' = last Friday of month) or alone in day-of-month ('L' = last day); elsewhere it is a syntax error. Note the exception message uses the outer variable i (often 0 here) rather than the actual position, so the reported pos can be misleading.
Solutions
- Move the 'L' to a field where it is valid: use 'L' alone in day-of-month for 'last day of month', or '<n>L' in day-of-week for 'last <n> weekday of month'.
- Remove the stray 'L' from the invalid field and keep the plain numeric value.
- Validate with CronExpression.isValidExpression before storing the cron string in configuration.
Example fix
// before String cron = "0 9L * * * ?"; // throws: 'L' option is not valid here // after String cron = "0 0 9 L * ?"; // 09:00 on the last day of the month
Defensive patterns
Strategy: try-catch
Validate before calling
if (!org.activiti.engine.impl.calendar.CronExpression.isValidExpression(cronString)) {
throw new IllegalArgumentException("Invalid cron expression: " + cronString);
} Try / catch
try {
new CronExpression(cronString);
} catch (java.text.ParseException e) {
if (e.getMessage().contains("'L' option is not valid")) {
// 'L' is only valid in day-of-month (alone) or day-of-week (as '<n>L');
// report the offending field to the user
}
} Prevention
- Use 'L' only as: day-of-month 'L' (last day) or day-of-week '<n>L' (last nth weekday).
- Validate cron strings with CronExpression.isValidExpression at config-load time, not first fire time.
- When translating cron between dialects, translate special characters per target-field rules.
When it happens
Trigger: A cron expression containing 'L' in a field where it is not allowed, e.g. '0 0 L * * *'? no wait, day-of-month 'L' is handled elsewhere; concrete trigger is 'L' following a value parsed by checkNext in a non-DAY_OF_WEEK field, e.g. hours field '9L' ('0 9L * * *') or minute field '5L', or 'L' suffix on a month value.
Common situations: Copy-pasting cron strings between dialects where L is accepted in day-of-month but written into the wrong field; typos like '5L' in minute fields; generated expressions appending L after a generic numeric field; misunderstanding Quartz's field-specific L semantics.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- 'W' option is not valid here. (pos=)
- Day of month values must be between 1 and 31
- Failed to parse cron expression:
- Hour values must be between 0 and 23
- Illegal cron expression format
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/5b51d20e7eaaad8b.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/calendar/CronExpression.java:567
}
protected int checkNext(int pos, String s, int val, int type) 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(Integer.valueOf(val));
i++;
return i;
}
if (c == 'W') {
if (type == DAY_OF_MONTH) {
nearestWeekday = true;
} else {
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
);
TreeSet<Integer> set = getSet(type);View on GitHub (pinned to 56435b1a97)