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

  1. Not reachable through normal cron parsing; if hit, capture the exact cron expression and file a bug against the calendar component
  2. 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)