flowable/flowable-engine · error · java.lang.IllegalArgumentException
Unexpected type encountered
Error message
Unexpected type encountered
What it means
Defensive switch guard inside CronExpression: while computing a wrapped range (stopAt < startAt overflow handling) the calendar field type is not one of SECOND/MINUTE/HOUR/MONTH/DAY_OF_WEEK/DAY_OF_MONTH, i.e. an unhandled/unknown type token reached internal logic. It is a sentinel for an impossible-by-construction state, indicating corrupted parsing state or a code path passing an invalid type.
Solutions
- Not reachable through normal cron parsing; if hit, capture the exact cron expression and file a bug against the calendar component
- Verify any custom code that calls CronExpression internals with hand-built type constants
Defensive patterns
Strategy: type-guard
When it happens
Trigger: Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:1074 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f40c4f4397e17ed8.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:1074
}
}
// if the end of the range is before the start, then we need to overflow
// into
// the next day, month etc. This is done by adding the maximum amount
// for that
// type, and using modulus max to determine the value being added.
int max = -1;
if (stopAt < startAt) {
max = switch (type) {
case SECOND -> 60;
case MINUTE -> 60;
case HOUR -> 24;
case MONTH -> 12;
case DAY_OF_WEEK -> 7;
case DAY_OF_MONTH -> 31;
case YEAR -> throw new IllegalArgumentException("Start year must be less than stop year");
default -> throw new IllegalArgumentException("Unexpected type encountered");
};
stopAt += max;
}
for (int i = startAt; i <= stopAt; i += incr) {
if (max == -1) {
// ie: there's no max to overflow over
set.add(i);
} else {
// take the modulus to get the real value
int i2 = i % max;
// 1-indexed ranges should not include 0, and should include
// their max
if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH)) {
i2 = max;
}
View on GitHub (pinned to d6d39ce1c6)