jeecgboot/JeecgBoot · error · IllegalArgumentException

Illegal month number: ${monthNum}

Error message

Illegal month number: ${monthNum}

What it means

Thrown as IllegalArgumentException from getLastDayOfMonth when the monthNum parameter does not match any of the switch cases 1–12. This is a defensive guard in a method that returns the number of days in a given month (accounting for February leap years via a separate check). Under normal operation the monthNum always comes from validated cron data and is 1–12; this error indicates corrupted state or an unexpected code path feeding an invalid month.

Source

Thrown at jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:1642

                return 30;
            case 5:
                return 31;
            case 6:
                return 30;
            case 7:
                return 31;
            case 8:
                return 31;
            case 9:
                return 30;
            case 10:
                return 31;
            case 11:
                return 30;
            case 12:
                return 31;
            default:
                throw new IllegalArgumentException("Illegal month number: "
                        + monthNum);
        }
    }


    private Optional<Integer> findSmallestDay(int day, int mon, int year, TreeSet<Integer> set) {
        if (set.isEmpty()) {
            return Optional.empty();
        }

        final int lastDay = getLastDayOfMonth(mon, year);
        // For "L", "L-1", etc.
        final int smallestDay = Optional.ofNullable(set.ceiling(LAST_DAY_OFFSET_END - (lastDay - day)))
                .map(d -> d - LAST_DAY_OFFSET_START + 1)
                .orElse(Integer.MAX_VALUE);

        // For "1", "2", etc.
        SortedSet<Integer> st = set.subSet(day, LAST_DAY_OFFSET_START);

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. If calling getLastDayOfMonth directly from custom code, validate monthNum is 1–12 before invoking.
  2. Ensure the cron expression's month field passed validation — check for error 311 in logs.
  3. Verify thread safety: CronExpression objects should not be shared across threads without synchronization if fields can change.

Example fix

// before
int days = cronExpression.getLastDayOfMonth(0, 2024);  // 0 is invalid
// after
int days = cronExpression.getLastDayOfMonth(1, 2024);  // January
Defensive patterns

Strategy: try-catch

Validate before calling

if (monthNum < 1 || monthNum > 12) {
    throw new IllegalArgumentException("Month must be 1-12, got: " + monthNum);
}
int days = cronExpression.getLastDayOfMonth(monthNum, year);

Type guard

boolean isValidMonthNum(int monthNum) {
    return monthNum >= 1 && monthNum <= 12;
}

Try / catch

try {
    int days = cronExpression.getLastDayOfMonth(mon, year);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Illegal month number")) {
        // log and handle corrupted month state; reset CronExpression
    }
    throw e;
}

Prevention

When it happens

Trigger: Internal call to getLastDayOfMonth with a value outside 1–12 — e.g., 0, 13, or a negative number. This would require the cron expression's month field to have bypassed the addToSet range check (error 311) or for month data to be corrupted in memory.

Common situations: Extremely rare in practice; could occur if the CronExpression object is modified reflectively, if a subclass overrides month handling, or if there is a concurrency issue where the TreeSet is modified during iteration. Most likely indicates a bug in custom code that calls getLastDayOfMonth directly.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/143f3dc246ea041e. Report an issue: GitHub.