jeecgboot/JeecgBoot · error · IllegalArgumentException

Illegal month number

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.

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.

Appendix: 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)