lintcron
See exactly which cron field is wrong — and why.
Type a cron expression, get instant field-by-field feedback. See what it means in plain English and when it runs next. Everything happens in your browser.
dow: value 8 is out of range (0-7)
Cron expression syntax: where the spec ends and the runtimes diverge
POSIX.2-1992 §3 defines the canonical five-field cron syntax (minute, hour, day-of-month, month, day-of-week), and that document is the only thing every "cron" implementation actually agrees on. Everything past that line, the seconds field, the year field, the L/W/#/? characters, the timezone behavior, is an extension that some specific runtime grafted on later.
That divergence is why an expression that runs cleanly on a Linux box gets rejected by GitHub Actions, accepted but interpreted differently by Quartz, and silently truncated by AWS EventBridge.
Five-field syntax: POSIX origins and field ranges
The POSIX five-field form is unambiguous. Field 1 is minute (0–59). Field 2 is hour (0–23, where 24 is invalid and 0 means midnight). Field 3 is day-of-month (1–31). Field 4 is month (1–12 or JAN–DEC). Field 5 is day-of-week (0–7, where both 0 and 7 mean Sunday for historical Vixie cron compatibility). The special characters in pure POSIX are *, ,, -, and /.
# 9:00 AM every weekday, POSIX five-field
0 9 * * 1-5Step intervals like */5 are not in POSIX.2 itself; they came in as a Vixie cron extension, then BSD and GNU adopted them, which is why every modern Unix daemon supports */5 even though the original spec does not. We treat steps as part of the de-facto POSIX baseline because rejecting them would make the validator useless against real-world crontabs.
When day-of-month and day-of-week are both restricted (neither one is *), Vixie cron applies an OR: the job fires when either field matches. ISC cron and dcron behave the same way. Quartz reverses this and requires one of the two fields to be ?. The failure mode we kept hitting in our test corpus was 0 0 15 * 1, written by someone expecting "the 15th, only if it's a Monday." On a Linux host that fires every 15th and every Monday.
The Quartz extensions: seconds, year, and L/W/#
Quartz, written for the Java scheduler ecosystem, standardized a six- and seven-field form: seconds (0–59), minute, hour, day-of-month, month, day-of-week, year (1970–2099). It also introduced four characters POSIX does not recognize.
# Quartz seven-field: 9:00:00 AM, weekdays, in 2026 only
0 0 9 ? * MON-FRI 2026L means "last." L in day-of-month is the last day of the month; 5L in day-of-week is the last Friday. W picks the weekday nearest a date: 15W fires on the closest weekday to the 15th. # selects the nth weekday: 6#3 is the third Friday. ? is "no specific value" and exists because Quartz forbids both day-of-month and day-of-week from being constrained at once.
Where platform runtimes diverge from the spec
| Special character | Unix 5-field | Quartz 7-field | Kubernetes CronJob | GitHub Actions | AWS EventBridge |
|---|---|---|---|---|---|
| * | yes | yes | yes | yes | yes (? required in DOM or DOW) |
| , - / | yes | yes | yes | yes | yes |
| L (last) | no | yes | no | no | yes |
| W (weekday nearest) | no | yes | no | no | yes |
| # (nth weekday) | no | yes | no | no | yes |
| ? (no value) | no | yes (required) | no | no | yes (required) |
| Seconds field | no | yes | no | no | no |
| Year field | no | yes | no | no | yes (6 fields, no seconds) |
Kubernetes CronJob runs cron from the robfig Go library and rejects ? outright, so an expression copied from Quartz config fails the admission webhook with a parser error that doesn't name the offending character. GitHub Actions runs in UTC always and ignores any host or workflow timezone setting, which catches teams whose crontab uses local time. The Actions runner also silently caps minute steps at five, so */3 * * * * in a workflow file does not fire every three minutes; the smallest interval the scheduler respects is five. AWS EventBridge looks Quartz-shaped at first glance but drops the seconds field, leaving a six-field form that demands ? in exactly one of day-of-month or day-of-week. That's why 0 12 * * MON-FRI * is invalid on EventBridge yet valid on a Linux box. Vixie cron and ISC cron honor @reboot, @daily, @hourly, and the other named shorthands; Quartz, Kubernetes, GitHub Actions, and EventBridge reject them.
The validator picks a dialect from the field count and from optional L/W/#/? presence, then walks each field against that dialect's range, returning the field index and the reason together when something fails.
Frequently Asked Questions
How do I validate a cron expression?
Why is my cron expression not working?
How do I know which field of my cron expression is wrong?
What is the difference between Unix cron and Quartz cron?
How do I write a cron expression for Kubernetes CronJobs?
How do I write a cron expression for GitHub Actions?
What does the seconds field do in a 6-field cron expression?
Can I use L, W, or # in a Unix cron expression?
What does '0 9 * * 1-5' mean?
Why does crontab.guru not show me errors?
Your data stays put
No accounts. No server calls. Everything runs in your browser. See our Privacy Policy for details.