What the CRON_ERR Error Means
The cron scheduler does not output a single numeric failure code like Windows does. A CRON_ERR entry or messages like (CRON) error in system logs are an aggregate indicator that the daemon failed to execute a scheduled job or that the job itself terminated with a non-zero exit status.
You will encounter this problem when automated scripts stop running on schedule, files aren't updated, or you receive empty emails with codes 1, 126, 127. The error manifests strictly in the background, so without explicit logging, it's easy to miss until critical consequences accumulate.
Common Causes
A scheduler failure almost always boils down to one of the following factors:
- Incorrect paths in the
$PATHvariable. Cron runs jobs with a minimal environment where/usr/local/binor/snap/binmay be missing. - Missing execute permissions. The script file lacks the
+xbit, or the user is not listed in/etc/cron.allow. - Interactive prompts. The script requires a password,
sudoconfirmation, or terminal output, which is impossible for a background daemon. - Resource contention and locking. Two jobs attempt to write to the same log file or database simultaneously without a
flockmechanism. - Corrupted crontab tables. Invalid syntax in a line (e.g., a space instead of a tab or a missing minute field) causes the parser to discard the entire task.
Solutions
Method 1: Check Service Status and Restart
First, ensure the scheduler daemon itself is running correctly. Depending on the distribution, the service is called cron (Debian/Ubuntu) or crond (RHEL/AlmaLinux).
# Check status (Ubuntu/Debian)
systemctl status cron
# Check status (RHEL/CentOS/Alma)
systemctl status crond
If the output shows inactive (dead) or failed, start the service and enable it at boot:
sudo systemctl enable --now cron # or crond
💡 Tip: If the service fails immediately after starting, check the syntax of all user crontabs with
crontab -e—one incorrect character can block the daemon from loading.
Method 2: Review System Logs and Debug Output
Standard cron errors are logged to syslog or the journal. Filter events from the last hour to find the exact failure line:
journalctl -u cron --since "1 hour ago" | grep -i error
To debug a specific task, temporarily redirect its standard output and error stream to a temporary file. Add >> /tmp/task_debug.log 2>&1 to the end of the crontab line:
*/5 * * * * /opt/scripts/backup.sh >> /tmp/cron_debug.log 2>&1
After the schedule triggers, open /tmp/cron_debug.log—it will contain the exact error text emitted by your script.
Method 3: Configure Environment Variables and Absolute Paths
The most frequent cause of exit code 127 (command not found) is missing full paths. Cron does not inherit your .bashrc or .profile.
- Open the job table:
crontab -e - Add explicit environment variables at the very top of the file:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
- Replace relative calls with absolute ones. Instead of
python3 script.py, use/usr/bin/python3 /home/user/scripts/task.py.
Method 4: Check Access Lists and Lock Files
If (username) ACCESS DENIED appears in logs, check the access control configuration.
# Check for existence of control files
ls -la /etc/cron.allow /etc/cron.deny 2>/dev/null
- If
/etc/cron.allowexists, your user must be listed in it. Thecron.denyfile is ignored in this case. - If neither file exists, access is open to all users except
root(on some distributions) and users with/sbin/nologinshell.
To prevent conflicts from multiple concurrent instances, use flock directly in the crontab line:
0 2 * * * /usr/bin/flock -n /tmp/backup.lock /opt/scripts/backup_daily.sh
The -n flag ensures an immediate exit without starting if the previous job is still running.
Prevention
- Always use full paths to binaries and scripts. Do not rely on user environment variables.
- Configure
MAILTOor redirect logs to a dedicated directory like/var/log/cron_tasks/. This allows you to track job status without manual server login. - Avoid
sudoinside crontab entries. Run jobs as the correct user viasudo -u username crontab -eor configuresudoerswith theNOPASSWDoption. - Regularly review schedules with
crontab -lafter making changes. A single misplaced comma can shift execution by a month. - For complex jobs with dependencies, consider migrating to
systemd timers—they provide better environment isolation and built-in restart mechanisms on failure.