xuxueli/xxl-job · error · ParseException

Day of month values must be between 1 and 31

Error message

Day of month values must be between 1 and 31

What it means

Thrown by CronExpression's field-validation routine (addToSet) when the DAY_OF_MONTH token holds a value below 1 or above 31, or a range whose upper bound exceeds 31. Both wildcards are allowed: ALL_SPEC_INT (99, for '*') and NO_SPEC_INT (98, for '?'), so any literal day-of-month must be 1-31.

Source

Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:1000

            throws ParseException {

        TreeSet<Integer> set = getSet(type);

        if (type == SECOND || type == MINUTE) {
            if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) {
                throw new ParseException(
                        "Minute and Second values must be between 0 and 59",
                        -1);
            }
        } else if (type == HOUR) {
            if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) {
                throw new ParseException(
                        "Hour values must be between 0 and 23", -1);
            }
        } else if (type == DAY_OF_MONTH) {
            if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT)
                    && (val != NO_SPEC_INT)) {
                throw new ParseException(
                        "Day of month values must be between 1 and 31", -1);
            }
        } else if (type == MONTH) {
            if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) {
                throw new ParseException(
                        "Month values must be between 1 and 12", -1);
            }
        } else if (type == DAY_OF_WEEK) {
            if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT)
                    && (val != NO_SPEC_INT)) {
                throw new ParseException(
                        "Day-of-Week values must be between 1 and 7", -1);
            }
        }

        if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) {
            if (val != -1) {
                set.add(val);

View on GitHub (pinned to e74c784f68)

Solutions

  1. Constrain day-of-month literals to 1-31; there is no day 0.
  2. Use '*' for any day or '?' to leave day-of-month unspecified (required when you specify day-of-week instead).
  3. Validate generated cron strings with a parse test before saving.

Example fix

// before
new CronExpression("0 0 12 32 * ?"); // day 32 invalid
// after
new CronExpression("0 0 12 15 * ?"); // day 15
Defensive patterns

Strategy: validation

Validate before calling

// Guard day-of-month literals 1-31 before parsing
String[] f = expr.trim().split("\\s+");
String dom = (f.length >= 6) ? f[3] : f[2];
if (dom.matches("\\d+")) {
    int d = Integer.parseInt(dom);
    if (d < 1 || d > 31) throw new IllegalArgumentException("day-of-month out of range: " + d);
}

Try / catch

try {
    CronExpression c = new CronExpression(expr);
} catch (java.text.ParseException e) {
    log.warn("Invalid cron '{}': {}", expr, e.getMessage());
}

Prevention

When it happens

Trigger: Constructing CronExpression with a day-of-month like "32", "0", or a range "1-35". Raised during parsing/construction of the CronExpression.

Common situations: Typos in hand-written cron (e.g. day 32); calendar-generation code that emits up to 31 plus a stray increment; tools that permit 0 as a day.

Related errors


AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14). Data as JSON: /api/errors/9650d1cd170d1808. Report an issue: GitHub.