Skip to main content
C
CodeUtil

Crontab Validation: Common Mistakes and How to Fix Them

Cron expressions have caused me more 3 AM incidents than I care to admit. Here is my guide to validating them properly, plus every mistake I have made so you do not have to.

2024-07-308 min
Related toolCrontab Validator

Use the tool alongside this guide for hands-on practice.

Why I built a cron validator

Here is a fun story: I once deployed a cron job meant to run weekly that actually ran every minute. For six hours. That database cleanup script deleted way more than intended. Since then, I always validate cron expressions before they hit production.

Cron syntax looks simple, but the edge cases are brutal. Wrong field order, timezone confusion, platform differences - I have been bitten by all of them at Šikulovi s.r.o..

The 5-field format I use daily

Standard cron is 5 fields, left to right: minute (0-59), hour (0-23), day of month (1-31), month (1-12), day of week (0-6, Sunday is 0). I remember it as "minutes matter most" since minute comes first.

  • * * * * * runs every minute - use sparingly, this adds up fast
  • 0 * * * * runs at the top of every hour - my go-to for hourly jobs
  • 0 0 * * * runs at midnight daily - careful with timezones on this one
  • 0 9 * * 1-5 runs at 9 AM weekdays - perfect for business-hours tasks
  • */15 * * * * runs every 15 minutes - I use this for health checks

Mistakes I have made (so you do not have to)

I have made every single one of these errors. Some in production. Learn from my pain.

  • Using 6 fields when the system expects 5 - some platforms add seconds, most do not
  • Minute value of 60 - valid range is 0-59, I got burned by this once
  • Hour value of 24 - valid range is 0-23, midnight is 0 not 24
  • Day of week 7 - Sunday is 0, Saturday is 6, there is no 7
  • Using */0 - step must be at least 1, */0 is not "never"
  • Months 0-11 vs 1-12 - cron uses 1-12, unlike JavaScript Date

Special characters I use most

Beyond the basics, these special characters let me build complex schedules. I use */n constantly for intervals.

  • * matches any value - the wildcard
  • */n runs every n units - */5 for every 5 minutes, my most-used pattern
  • n,m specifies multiple values - 1,15 for 1st and 15th of the month
  • n-m defines a range - 1-5 means Monday through Friday
  • L means last - great for month-end processing
  • # specifies nth occurrence - 1#2 is the second Monday

Platform differences will trip you up

This caught me when I moved a cron from a Linux server to AWS EventBridge - completely different format. EventBridge uses 6 fields with year support. Quartz scheduler uses 6-7 fields with seconds. GitHub Actions is standard 5-field but always UTC.

I always check platform docs now before copy-pasting cron expressions. The syntax looks similar but the behavior differs.

The timezone trap

Cron runs in the server local timezone. This sounds fine until daylight saving time shifts your 2 AM backup job, or your container runs in UTC while you expected CET. I have learned to always document which timezone my crons expect.

For critical jobs, I use UTC exclusively now. It is one less variable that can break things at 3 AM.

My testing ritual before deployment

I never deploy a cron expression without validating it first. The tool shows me exactly when the next runs will happen. This catches off-by-one errors and timezone surprises before they become production incidents.

FAQ

Is my cron data secure when validating?

Yes - all validation runs in your browser. I built it this way because I would never paste production cron expressions into a tool that sends data to unknown servers.

What cron format does the validator support?

The standard 5-field format used by Linux crontab, Kubernetes CronJobs, and GitHub Actions. If you need AWS EventBridge or Quartz validation, those use different formats that I do not support yet.

Why does my cron expression show as invalid?

Usually it is wrong field count, out-of-range values, or invalid special characters. Double-check that you have exactly 5 fields and all numbers are within valid ranges. I have been bitten by all of these.

How do I schedule a job for the last day of the month?

Use L in the day-of-month field: "0 0 L * *" runs at midnight on the last day of every month. Fair warning - not all cron implementations support L.

Can I validate multiple cron expressions at once?

Yes - paste one expression per line and I will check each individually. I use this when auditing crontabs with dozens of entries.

Martin Šikula

Founder of CodeUtil. Web developer building tools I actually use. When I'm not coding, I experiment with productivity techniques (with mixed success).

Related articles