Migrating production infrastructure? Get up to ₹10,000 in migration credits. Apply now
voroaBlog
Background Workers

Cron Job Not Running? A 12-Point Checklist That Finds It

· · 5 min read

Cron job not running, a 12-point checklist from the daemon and PATH to timezones and overlap

A cron job not running is one of the most annoying problems in operations, because nothing tells you. There is no error on screen, and the job simply does not happen.

The cause is almost always one of a short list. Work through the checks below in order. The first few take seconds, and together they cover the vast majority of cases.

On this page

Advertisement

First: did it run at all?

Before changing anything, find out whether cron started the job and it failed, or never started it.

bash
grep CRON /var/log/syslog          # Debian and Ubuntu
journalctl -u cron --since today   # systemd (the unit is crond on RHEL-family systems)

A line with your command means cron started it, so the problem is inside the command (checks 5 to 8). No line means cron never ran it (checks 1 to 4 and 9).

Diagram: a decision tree for a cron job that is not running - check the cron log; if cron started the job, debug the command (PATH, environment, permissions, output); if it never started, check the daemon, the crontab, the syntax and the timezone

Checks 1-4: is cron set up?

1. Is the cron daemon running? On Ubuntu, systemctl status cron. In a minimal Docker container there is usually no cron daemon at all unless you start one.

2. Is the job in the crontab you think? Run crontab -l as the same user. A job added with sudo crontab -e lives in root’s crontab, not yours.

3. Is the syntax right? Standard cron takes five time fields. A sixth field for seconds, copied from a library such as node-cron, makes the line invalid. Files in /etc/cron.d/ also need a user name before the command.

4. Does the file end with a newline? Cron can ignore a last line with no newline after it. Press Enter after the final job.

Checks 5-8: does the command work under cron?

5. The PATH is short. Cron runs with a minimal PATH, often just /usr/bin:/bin. A command such as node, python3 or php installed elsewhere is not found. Use full paths (which node shows it), or set PATH= at the top of the crontab.

6. Your environment is not loaded. Cron does not read .bashrc or .profile. Variables such as DATABASE_URL that you export in your shell are missing. Load them explicitly in the script.

7. The % sign is special. In a crontab, % means “new line”. A command such as date +%Y-%m-%d breaks unless you write \%. Moving the command into a script avoids it.

8. Permissions and the working directory. The script must be executable (chmod +x), and cron starts in your home directory. A script that opens config.json by relative path fails. cd to the right folder first.

Checks 9-12: is it running at the wrong time, or twice?

9. The timezone. Cron uses the server’s timezone, usually UTC in the cloud. A job meant for 9 am in India written as 0 9 * * * runs at 2:30 pm. Write 30 3 * * *, or change the server timezone.

10. Day-of-month and day-of-week. If both are set, standard cron runs when either matches. 0 9 1 * 1 runs on the 1st and every Monday, which looks like “running at random”.

11. Overlapping runs. A slow run is still going when the next one starts. They clash, and one seems to fail. Wrap the command in flock -n /tmp/job.lock so a second copy is skipped.

12. It runs on two machines. The same crontab on two servers, or an in-app scheduler in two instances, runs every job twice. We measured exactly that with node-cron and APScheduler.

Extra traps on hosted platforms

Platform What stops a job running
GitHub Actions Minimum 5-minute interval; delays at busy times; disabled after 60 days without activity in public repositories
Vercel Only production deployments run crons; redirects (such as trailingSlash) end the run; Hobby allows one run a day on legacy Cron Jobs
Heroku Scheduler A run is stopped at its interval; runs are best-effort
Celery beat Two beat processes double tasks; a lost schedule file loses last-run times
Voroa The parent service must be running; runs are skipped while it is stopped, including after a free workspace uses its monthly free hours

Sources: the GitHub Actions schedule docs and each platform’s own documentation. More detail per platform is in our posts on Vercel cron jobs and Heroku Scheduler.

A crontab line that avoids most of this

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
CRON_TZ=Asia/Kolkata

30 9 * * * cd /srv/app && flock -n /tmp/digest.lock ./bin/digest >> /var/log/digest.log 2>&1

It sets a shell and a PATH, runs from the right folder, takes a lock, and logs both output and errors. CRON_TZ is honoured by cronie (Fedora, RHEL); Ubuntu’s default cron ignores it, so check yours.

On Voroa

A Voroa Cron Job or Scheduled Task runs your command inside a service that stays running, with your environment variables already set and schedules in India Standard Time. That removes checks 5, 6 and 9, though the container’s own clock may still read UTC if your job reads the date.

Voroa does not show per-run output for a scheduled command, so make the job record its result somewhere you can check, such as a database row. See scheduling a task on Voroa and worker or cron job. Long-running processes are covered on the background workers page.

FAQ

Why is my cron job not running? Most often: a missing PATH, a missing environment variable, a timezone difference, or the job is in a different user’s crontab. Check the cron log first to see whether it started at all.

How do I check if cron ran my job? Look for your command in /var/log/syslog (Debian, Ubuntu) or journalctl -u cron, and send the job’s own output to a log file.

Why does my script work in the terminal but not in cron? Cron has a short PATH, does not load your shell profile, and starts in your home directory. Use full paths and load your variables in the script.

Why does my cron job run at the wrong time? The server is probably on UTC. For 9 am IST on a UTC server, write 30 3 * * *.

How do I stop a cron job running twice? Use flock -n against overlap, and make sure only one machine or one scheduler instance runs the job.

Does cron run if the server was off? No. Standard cron does not catch up missed runs. systemd timers can, with Persistent=true.

Updated 7 November 2026. Found something out of date? Write to [email protected].

Advertisement