Skip to content
Get started

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:

crontab entry
0 3 * * * /usr/local/bin/nightly.sh >> /var/log/nightly.log 2>&1

How 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>"
This is exactly where the log-aware diagnosis earns its keep: a bare exit 1 is useless, but on paid tiers CronShield reads the failing run's last log lines and puts the actual exception plus a likely cause in the alert. PING_URL is a placeholder for the endpoint you get on a monitor.

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.