Exit code 1: a general error (read the log, not the code)
Exit code 1 is the catch-all failure status: the command ran and reported an error, but the code itself tells you nothing specific about what went wrong. Unlike 127 (not found) or 137 (killed), a 1 means "something the program did failed" — so the cause lives in the log output, not the number. Read the last few log lines to find the actual exception, message, or failed step.
What does exit code 1 mean?
By convention a program returns 0 on success and a non-zero code on failure. 1 is the generic, unspecified failure code most programs use when they don't have a more specific one. A Python script that raises an uncaught exception exits 1; a shell command that fails with `set -e` exits 1; a linter or test runner that found problems often exits 1. The number is the same regardless of cause.
That's why the exit code alone can't diagnose a 1 — the meaningful signal is in the last lines the job printed before it exited.
How do I find the real cause of an exit 1?
- Read the tail of the log: the exception, stack trace, or error message on the last few lines is the actual cause. A Python `Traceback (most recent call last):` block ends with the exception type and message that triggered the exit.
- Reproduce with output visible: run the command directly (not through cron's redirected output) so you see stderr, or make cron capture it with `>> /var/log/job.log 2>&1`.
- Check what changed: a job that worked yesterday and exits 1 today usually points at changed input data, a dependency update, an expired credential, or an unreachable service.
How do I capture the log so I can diagnose the 1?
cron discards output by default (or emails it to the local mailbox, which is often unread). Redirect both stdout and stderr to a file so the failing output survives:
0 3 * * * /usr/local/bin/nightly.sh >> /var/log/nightly.log 2>&1How do I get alerted with the cause, not just the code?
A missed-ping monitor tells you the run didn't succeed. Because a 1 is opaque, the useful thing is the log line behind it. Ping only on success so a 1 withholds the ping and alerts:
/usr/local/bin/nightly.sh && curl -fsS -m 10 --retry 3 "https://ping.cronshield.com/<your-check-id>"Catch this failure automatically
The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.
Frequently asked questions
- Why does my cron job exit 1 with no useful message?
- Because cron discards output by default, you often see the code but not the error. Redirect stdout and stderr to a file (`>> /var/log/job.log 2>&1`) so the exception or message that caused the 1 is captured, then read the last lines.
- Is exit 1 always a bug in my code?
- No. Exit 1 just means the program reported a failure. It could be your code raising an exception, but it could equally be bad input, an expired token, a service that was down, or a dependency change. The log tail tells you which.
Primary sources
- GNU Bash Manual — Exit Status (0 success, non-zero failure; 1 = generic error) — verified 2026-07-04
- Python docs — sys.exit and uncaught exceptions exit with status 1 — verified 2026-07-04