cronalertsclitutorial

How to Get Notified When a Cron Job Fails Silently

February 5, 2026

Cron jobs fail silently. Your nightly backup stops running, and nobody notices for three weeks until someone actually needs that backup. There’s no error page, no user complaint, just silence.

Here’s how to fix that with push notifications.

Why cron jobs fail silently

Cron doesn’t care if your script exits with an error. It runs the command, discards the output, and moves on. Unless you’ve explicitly configured MAILTO (and your server can actually send email), a failing cron job looks identical to a successful one. It just runs and produces nothing.

Common failure modes:

  • A dependency isn’t available (database down, API unreachable)
  • A script path changed after a deployment
  • Permissions changed on a file or directory
  • Disk space ran out mid-operation
  • The script itself has a bug that only surfaces with certain data

All of these fail silently by default.

The simplest fix: exit codes and conditional alerts

Every shell command returns an exit code. 0 means success, anything else means failure. You can use this to trigger an alert only when something goes wrong.

#!/bin/bash

/usr/local/bin/backup.sh
if [ $? -ne 0 ]; then
  curl -X POST https://api.apialerts.com/event \
    -H "Authorization: Bearer $APIALERTS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"channel": "ops", "message": "Nightly backup failed", "tags": ["cron", "backup"]}'
fi

This works, but there’s a simpler way if you don’t want to write wrapper scripts for every cron job.

Using the API Alerts CLI (no code required)

If you’d rather not manage curl commands or wrapper scripts, the API Alerts CLI does the same thing in a single line:

apialerts send --channel ops --message "Nightly backup failed" --tags cron,backup

You can chain this directly in your crontab using ||, which only executes the right side if the left side fails:

# Alert on failure only
0 3 * * * /usr/local/bin/backup.sh || apialerts send --channel ops --message "Nightly backup failed on $(hostname)"

Or alert on success too, so you have a positive confirmation that the job ran:

# Alert on both success and failure
0 3 * * * /usr/local/bin/backup.sh && apialerts send --channel ops --message "Backup complete" || apialerts send --channel ops --message "Backup failed on $(hostname)"

Alerting from a Python cron job

If your scheduled task is a Python script, you can use the API Alerts Python SDK to send alerts directly from your code:

from apialerts import ApiAlerts

client = ApiAlerts(api_key="your-api-key")

def run_cleanup():
    # your cleanup logic here
    deleted = cleanup_expired_sessions()
    return deleted

try:
    count = run_cleanup()
    client.send(channel="ops", message=f"Session cleanup complete, {count} removed")
except Exception as e:
    client.send(channel="ops", message=f"Session cleanup failed: {e}", tags=["error", "cron"])

The same pattern works with every API Alerts SDK: JavaScript, Go, Kotlin, Rust, Swift, and C#.

Alerting from GitHub Actions scheduled workflows

If you’re running scheduled tasks as GitHub Actions workflows (using cron in the schedule trigger), you can use the API Alerts GitHub Action to alert on failure:

name: Nightly data sync
on:
  schedule:
    - cron: '0 4 * * *'

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - run: ./scripts/sync-data.sh

      - name: Alert on failure
        if: failure()
        uses: apialerts/notify-action@v2
        with:
          api_key: ${{ secrets.APIALERTS_API_KEY }}
          channel: 'ci'
          message: 'Nightly data sync failed'
          tags: 'cron,sync'

This catches failures in any previous step and sends you an alert.

What to alert on

Not every cron job needs the same level of attention. A practical approach:

Always alert on failure:

  • Backups
  • Billing or payment processing
  • Data migrations
  • Security scans

Alert on success too (positive confirmation):

  • Any job where silence is ambiguous. Did it succeed or did it not run at all?
  • Jobs that run infrequently (weekly, monthly) where you’d otherwise forget to check

Consider skipping alerts for:

  • High-frequency, low-impact jobs (every minute cache warm) where failure is self-healing

Routing alerts to the right place

Use channels to route alerts to the right people. A backup failure at 3am should go to the on-call engineer, not a channel the whole team checks during business hours.

Set up your channels in the dashboard and your cron jobs don’t need to know or care who gets the alert.

Next steps