What it means

crontab -e and crontab <file> parse the whole file before installing it. One bad line and nothing is installed:

crontab: installing new crontab
"/tmp/crontab.Pk3yQa/crontab":4: bad day-of-week
errors in crontab file, can't install.
Do you want to retry the same edit? (y/n)

The number after the file name is the line, and the words after it name the field that failed: bad minute, bad hour, bad day-of-month, bad month, bad day-of-week or bad command. Your previous crontab keeps running.

Common causes

1. Quartz or Spring syntax. 0 0 2 ? * MON is valid for Quartz, not for cron: ? gives bad day-of-month, and L, W or # are refused the same way. A leading seconds field is worse, since it often parses and shifts every field by one.

2. A value out of range. Minute 0 to 59, hour 0 to 23, day of month 1 to 31, month 1 to 12, day of week 0 to 7. 60, 24 or */60 in the hour field fail.

3. An environment line written like shell. export PATH=/usr/local/bin:/usr/bin:/bin gives bad minute. Crontabs take NAME=value, without export.

4. A line with no command. Five fields and nothing after them give bad command, often a line split in two by the editor.

5. A missing final newline. Debian's crontab refuses the file with new crontab file is missing newline before EOF, can't install.

6. Syntax from another scheduler. @every 5m belongs to Go libraries, rate(5 minutes) to AWS. Cron knows @reboot, @hourly, @daily, @weekly, @monthly and @yearly.

How to fix

  1. Read the line number in the message and open that line.
  2. Rewrite the schedule as five fields: 0 2 * * 1 for 02:00 every Monday.
  3. Replace export NAME=value with NAME=value.
  4. Rejoin split lines and make sure the file ends with a newline.
  5. With crontab -e, answer y to retry the same edit. With a file, fix it and run crontab file again, then check with crontab -l.

Is it just you?

Paste the five fields into the cron expression generator: it explains each field and lists the next run times in your timezone, before you install anything.

Get alerted next time

  • Use the same five-field expression and timezone for a healthcheck in cron mode: Hyperping expects a ping at every run the expression produces.
  • If an edit is refused and the job stops being installed, or runs at the wrong time, the missing ping alerts you once the grace period passes.
  • See how it fits with other scheduled jobs on cron job monitoring.