Common Gotchas
Cron's syntax is small, which means most mistakes with it are the same handful of quirks, over and over, across every developer who's used it. Here's the field guide, so you recognize them the first time instead of the third.
💡 The Bottom Line
Almost every "why didn't this run when I expected" surprise with cron traces back to one of
four things: which timezone the schedule actually runs in, the surprising OR-logic between
day-of-month and day-of-week, whether Sunday is 0 or 7, or assuming a shorthand alias like
@daily works everywhere it doesn't.
Gotcha 1: which timezone is this actually running in?
A cron expression itself has no timezone built into it — it's just five numbers. Whether
0 9 * * * means 9am server time, 9am UTC, or 9am in whatever timezone the scheduling
system is configured for depends entirely on the system running it. This is one of the single
most common sources of "why did this run 5 hours off from when I expected" bugs, especially when
a server's system timezone differs from what the person writing the expression assumed.
⚠️ Gotcha: always confirm the timezone explicitly
Before trusting a schedule in production, check (don't assume) what timezone the specific system uses — Unix cron typically uses the host machine's local system timezone, while many cloud schedulers default to UTC or let you set a timezone explicitly per schedule. When in doubt, look for an explicit timezone setting rather than trusting a guess.
Gotcha 2: day-of-month AND day-of-week is actually OR
This one catches even experienced developers. Intuitively, you'd expect setting both
the day-of-month and day-of-week fields to narrow a schedule down — "run only when both match."
Most cron implementations do the opposite: if both fields are restricted (not
*), the job runs when either one matches.
0 0 1 * 1
You might read this as "midnight, on the 1st of the month, if it's also a Monday" — a rare combination. It actually means: midnight on the 1st of the month, or midnight on any Monday — whichever comes first, every week. That's a dramatically more frequent schedule than most people expect from reading the expression.
⚠️ Watch Out
If you actually need "the 1st of the month and only if it's a Monday," most
standard cron implementations can't express that directly in five fields — you'd need
application logic inside the job itself to check the extra condition and exit early if it
doesn't match. Don't assume setting both fields gives you an AND; verify with a parser tool
(Lesson 5) whenever you set both fields to something other than *.
Gotcha 3: is Sunday 0 or 7?
The day-of-week field is documented as 0-6 with 0 meaning Sunday —
but many implementations also accept 7 as an alternate value for Sunday, for
compatibility with other conventions. Both often work, but which values are accepted (and
whether 7 is silently treated as Sunday or rejected) varies by implementation. Don't
assume — check the specific system's documentation if a schedule involves Sunday.
Gotcha 4: shorthand aliases aren't universal
@daily (roughly equivalent to 0 0 * * *)
@hourly (roughly equivalent to 0 * * * *)
Some cron implementations — including standard Unix cron — support convenient shorthand
aliases like @daily, @hourly, @weekly, and
@reboot. These are a nice readability win where they're supported. But they are
not universal — many cloud schedulers and other systems that adopted cron syntax
require the plain 5-field form only and will reject a shorthand alias outright. Don't assume a
shorthand you learned on one system will work on another; check first.
🙋 There Are No Dumb Questions
Q: Given all these quirks, is cron syntax actually reliable to use at all?
A: Yes — these are edge cases and easy-to-verify details, not reasons to avoid cron syntax.
The core five-field pattern (Lessons 2-4) is consistent everywhere it's used. The gotchas in
this lesson are exactly the kind of thing a quick check with a parser tool (Lesson 5) catches
before they ever reach production — that's the whole reason "verify, don't assume" has been a
theme throughout this track.
🔧 Try It Yourself
Take the expression 0 12 15 * 5 and, before checking a tool, write out in plain
English what you think it means — remembering the day-of-month/day-of-week OR quirk from
Gotcha 2. Then verify with a parser tool. (Hint: it fires at noon on the 15th of the month,
or at noon on any Friday — not only when both line up.)
✅ Quick Check
If both the day-of-month and day-of-week fields are set to specific (non-*)
values, when does the job run in most standard cron implementations?
That's the whole track — time for the recap.