devtools.codes

Why does my cron job run twice a month?

Your tool input is processed locally in your browser and is not intentionally uploaded to our servers. Advertising and analytics providers may still process normal page, device, cookie and network information.

A cron expression with both a day-of-month and a day-of-week field set to anything other than a wildcard almost never means what it looks like it means. The schedule 0 9 1 * MON, written to mean "9am on the 1st, if it's a Monday", actually runs on the 1st of every month regardless of weekday, and separately on every Monday. Those two fields are combined with an implicit OR, not an AND, and this single rule accounts for the large majority of cron jobs that run more often than their author intended.

The behaviour is specified, not a bug, and it dates back to the original cron implementation rather than being an inconsistency introduced by a particular scheduler. Most modern cron-compatible tools preserve it for compatibility, which means the trap persists even in schedulers written decades after the original. The exception that catches people out in the other direction: if either field is left as a wildcard, the OR rule stops mattering, because a wildcard matches everything and the other field alone determines the schedule.

The practical fix depends on what you actually meant. If you wanted "the 1st of the month, whatever day that falls on", leave day-of-week as a wildcard and use only day-of-month. If you wanted "every Monday", leave day-of-month as a wildcard and use only day-of-week. If you genuinely need "the first Monday of the month", cron's five fields cannot express that directly — most schedulers need either a wrapper script that checks the date, or a day-of-week value combined with external logic, since no standard cron field combination means "first occurrence of this weekday in the month".

A fast way to catch this before it ships: whenever a schedule uses both a specific day-of-month and a specific day-of-week in the same expression, treat that as a signal to pause and check what it actually produces, because the combination is unintuitive by specification rather than by accident. A tool that previews the next several run dates for a given expression settles the question immediately, which is more reliable than reasoning through the OR rule by hand under time pressure.

More on why does my cron job run twice a month?

Why does cron run my job on both the 1st and every Monday?

Because setting both day-of-month and day-of-week fields combines them with OR rather than AND. A schedule like 0 9 1 * MON runs on the 1st of the month regardless of weekday, and separately on every Monday — not only when the 1st happens to be a Monday. This is specified cron behaviour, not a scheduler bug.

How do I schedule something for the first Monday of every month?

Standard cron fields cannot express that directly, since no combination of the five fields means 'first occurrence of this weekday'. The usual approaches are a wrapper script that runs every Monday and checks whether the date falls within the first seven days of the month, or a scheduler extension that supports that condition natively.

Does the day-of-month and day-of-week OR rule apply if one field is a wildcard?

No. The OR behaviour only applies when both fields specify something other than a wildcard. If day-of-week is left as *, the schedule is governed purely by day-of-month, and vice versa. The confusing case is specifically when both fields are set to a specific value at the same time.

Is there a way to check what a cron expression will actually do before deploying it?

Yes — preview the next several run dates the expression produces rather than reasoning through the fields by hand. Seeing the actual dates immediately reveals an unintended OR combination, because the schedule will visibly run far more often than one date a month would suggest.

The tool behind this, and related guides