flowable/flowable-engine · error · ParseException

The 'W' option does not make sense with values larger than…

Error message

The 'W' option does not make sense with values larger than 31 (max number of days in a month)

What it means

checkNext validates that a day-of-month value used with the 'W' (nearest weekday) option is at most 31. Since no month has more than 31 days, '32W' or higher is meaningless and throws this ParseException.

Solutions

  1. Use a day value 1-31 with W (e.g. 31W)
  2. Use 'L' alone or 'LW' for last-day / last-weekday-of-month semantics
  3. Clamp day-of-month inputs before constructing the CronExpression

Example fix

// before
new CronExpression("0 0 0 32W * ?");
// after
new CronExpression("0 0 0 LW * ?"); // last weekday of month
Defensive patterns

Strategy: validation

Validate before calling

boolean validNW(String domField) {
    if (!domField.matches("\\d+W")) return true;
    int d = Integer.parseInt(domField.substring(0, domField.length() - 1));
    return d >= 1 && d <= 31;
}

Try / catch

try {
    CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
    if (e.getMessage().contains("'W' option does not make sense")) {
        throw new ConfigurationException("nW day value must be 1-31: " + expr, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Expressions like "0 0 0 32W * ?" where the value before 'W' exceeds 31.

Common situations: Off-by-one or 'last day' attempts (users writing 32W intending end-of-month); generated expressions with unclamped day values.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/16238530564bf1de. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:757

                }
                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) {
                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);
            set.add(val);
            i++;
            return i;
        }

        if (c == '#') {
            if (type != DAY_OF_WEEK) {
                throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i);
            }
            i++;
            try {
                nthdayOfWeek = Integer.parseInt(s.substring(i));
                if (nthdayOfWeek < 1 || nthdayOfWeek > 5) {
                    throw new Exception();

View on GitHub (pinned to d6d39ce1c6)