alibaba/spring-cloud-alibaba · error · ParseException
Offset from last day must be <= 30
Error message
Offset from last day must be <= 30
What it means
Thrown when the 'L' (last day) construct in the DAY_OF_MONTH field is given an offset larger than 30 via 'L-N' (guard at CronExpression.java:471-472). 'L-N' means 'N days before the last day of the month', so an offset beyond 30 is meaningless.
Source
Thrown at spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java:472
addToSet(ALL_SPEC_INT, -1, incr, type);
return i;
}
else if (c == 'L') {
i++;
if (type == DAY_OF_MONTH) {
lastdayOfMonth = true;
}
if (type == DAY_OF_WEEK) {
addToSet(7, 7, 0, type);
}
if (type == DAY_OF_MONTH && s.length() > i) {
c = s.charAt(i);
if (c == '-') {
final ValueSet vs = getValue(0, s, i + 1);
lastdayOffset = vs.value;
if (lastdayOffset > 30) {
throw new ParseException("Offset from last day must be <= 30", i + 1);
}
i = vs.pos;
}
if (s.length() > i) {
c = s.charAt(i);
if (c == 'W') {
nearestWeekday = true;
i++;
}
}
}
return i;
}
else if (c >= '0' && c <= '9') {
int val = Integer.parseInt(String.valueOf(c));
i++;
if (i >= s.length()) {
addToSet(val, -1, -1, type);View on GitHub (pinned to 115d590110)
Solutions
- Use an offset <= 30, e.g. 'L-31' -> 'L-5' for the 5th-to-last day.
- If you need a range of final days, enumerate them or use a step, not a large 'L-N'.
- Sanitize any templated offset value before injecting into the cron string.
Example fix
// before
new CronExpression("0 0 0 L-31 * ?");
// after
new CronExpression("0 0 0 L-5 * ?"); // 5 days before month end Defensive patterns
Strategy: validation
Validate before calling
// 'L-N' offset must be 0..30.
static boolean lastDayOffsetOk(String domField) {
if (!domField.startsWith("L-")) return true;
try {
int off = Integer.parseInt(domField.substring(2));
return off >= 0 && off <= 30;
} catch (NumberFormatException e) { return false; }
} Try / catch
try {
CronExpression cron = new CronExpression(raw);
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid cron expression: " + raw, e);
} Prevention
- Cap 'L-N' offsets at 30.
- Sanitize templated offset values before injection.
- Prefer 'L' for the last day rather than guessing offsets.
When it happens
Trigger: `new CronExpression("0 0 0 L-31 * ?")` (last-day offset 31). Any 'L-NN' in the day-of-month field where NN > 30.
Common situations: Developer misreads 'L-N' as 'last N days' or typos the offset; also from concatenating an unbounded value into the offset.
Related errors
AI-assisted analysis of alibaba/spring-cloud-alibaba@115d590110 (2026-08-14).
Data as JSON: /api/errors/5d013c88c8e24be1.
Report an issue: GitHub.