You write 0 0 1 * * 0 thinking it means "midnight on the 1st of the month, if that day is a Sunday." That is the natural reading. It is also wrong.

In classic cron, day-of-month and day-of-week do not combine with AND. They combine with OR. 0 0 1 * * 0 fires on the 1st of every month AND on every Sunday. Your monthly job just became a weekly job too, and nothing in the syntax warns you.

The five fields, in order

minute hour day-of-month month day-of-week
0 0 1 * 0

Minute is 0-59, hour is 0-23, day of month is 1-31, month is 1-12, day of week is 0-6 with 0 as Sunday (7 also means Sunday). The symbols are the whole language: * means every value, */15 means every 15th value, 9-17 is a range, 0,30 is a list. Month and weekday names work as well, so 0 0 * * mon is the same schedule as 0 0 * * 1.

Three schedules, read out loud

A nightly backup at 2:30 AM:

30 2 * * *

A report every 15 minutes during office hours on weekdays:

*/15 9-17 * * 1-5

And the trap, written plainly:

0 0 1 * * 0

That last one runs at midnight on the 1st of the month, and at midnight every Sunday. If you wanted only the 1st, the weekday field must stay *. If you wanted only Sundays, the day-of-month field must stay *. There is no way to express "the 1st, but only if it is a Sunday" in a single standard cron line.

A second trap: valid syntax, impossible date

0 0 31 2 * passes every syntax check. February 31 does not exist, so the job never runs, and nothing fails loudly. The only defence is previewing the next run times before the expression reaches production. A preview that searches a few years ahead and finds zero runs tells you the schedule is impossible, not merely unusual.

Build it instead of memorizing it

I built a small tool that does exactly this check: you pick a mode for each field, or paste an expression you already have, and it explains the schedule in plain English, lists the next five run times, and hands you a crontab line ready to paste. It also flags impossible schedules like February 31.

Try it here: https://www.theutilityhub.online/tools/cron-expression-builder

Everything runs in your browser, so schedules for internal jobs never leave your machine. One last warning the tool also states plainly: a cron expression carries no timezone. The preview shows your browser timezone, but your server may run UTC, and a 9 AM job silently becomes a 2 PM job if you do not check. Confirm the server timezone before you deploy, and let the preview catch the rest.