Cron Atlas

Spring error A value outside the field

Invalid value for HourOfDay (valid values 0 - 23): 24 '24' in cron expression "0 0 24 * * *"

java.lang.IllegalStateException: Encountered invalid @Scheduled method 'run': Invalid value for HourOfDay (valid values 0 - 23): 24 '24' in cron expression "0 0 24 * * *"
java.lang.IllegalStateException: Encountered invalid @Scheduled method 'run': Invalid value for DayOfMonth (valid values 1 - 28/31): 0 '0' in cron expression "0 0 9 0 * *"
java.lang.IllegalStateException: Encountered invalid @Scheduled method 'run': Invalid value for DayOfWeek (valid values 1 - 7): 8 '8' in cron expression "0 0 9 * * 8"

Message produced by running the expression through org.springframework.scheduling.support.CronExpression from Spring Framework 7.0.10, the parser behind @Scheduled. 6.2.19 prints the same.

What it means

Spring checks each number against the matching java.time field and passes on its message, which is why the field names are HourOfDay, MinuteOfHour, DayOfMonth, MonthOfYear and DayOfWeek rather than cron’s own names.

The ranges are second and minute 0–59, hour 0–23, day of month 1–31, month 1–12, and day of week 0–7, where 0 and 7 are both Sunday. The message says 1–7 for day of week because that is java.time’s range; Spring accepts 0 as well.

Rejected expressions and their fixes

Each expression opens in the tester. The message under a rejected one is what Spring Framework 7.0.10 printed for it.

  1. Rejected0 0 24 * * *Invalid value for HourOfDay (valid values 0 - 23): 24 '24' in cron expression "0 0 24 * * *"
    Use
    0 0 0 * * *At 00:00.

    Midnight is hour 0. There is no hour 24.

  2. Rejected0 60 * * * *Invalid value for MinuteOfHour (valid values 0 - 59): 60 '60' in cron expression "0 60 * * * *"
    Use
    0 0 * * * *Every hour, on the hour.

    Minutes stop at 59. Minute 0 of every hour is the top of the hour.

  3. Rejected0 0 9 0 * *Invalid value for DayOfMonth (valid values 1 - 28/31): 0 '0' in cron expression "0 0 9 0 * *"
    Use
    0 0 9 1 * *At 09:00, on the 1st of the month.

    Days of the month start at 1. For the last day of the month, use L: 0 0 9 L * *.

  4. Rejected0 0 0 1 0 *Invalid value for MonthOfYear (valid values 1 - 12): 0 '0' in cron expression "0 0 0 1 0 *"
    Use
    0 0 0 1 1 *At 00:00, on the 1st of the month, in January.

    Months run from 1 (January) to 12. Names such as JAN avoid the off-by-one.

  5. Rejected0 0 9 * * 8Invalid value for DayOfWeek (valid values 1 - 7): 8 '8' in cron expression "0 0 9 * * 8"
    Use
    0 0 9 * * 7At 09:00, on Sundays.

    Day of week stops at 7, which is Sunday. SUN says the same.

Questions

Is Sunday 0 or 7 in Spring cron?
Both. 0 and 7 mean Sunday and 1 is Monday, as in Unix cron. Quartz is different: there Sunday is 1.
Why does the message say “1 - 28/31” for day of month?
That is java.time’s way of saying the last valid day depends on the month. Spring itself accepts 1 to 31 and skips months that are too short.

Other Spring errors

Reference