Back to Articles How-to

How to Get Slack Notifications When Your Cron Job Fails

Julio Andres March 31, 2026 6 min read Slack · Cron · DevOps

Cron jobs are silent by default. They run in the background, and when they fail — whether it's a script error, a timeout, or a missing dependency — you usually find out hours later, when someone notices that the data wasn't processed or the backups didn't run.

The fix is simple: get a Slack message the moment a cron job exits with an error. Here's how to do it, from a quick shell script approach to a cleaner setup that works across all your jobs.

Option 1: Slack Webhooks (The Quick Way)

Slack lets you create an Incoming Webhook URL for a channel. You go to your Slack app settings, enable Incoming Webhooks, create one for the channel you want, and you get a URL. Then you POST to it:

Shell
#!/bin/bash
SLACK_WEBHOOK="https://hooks.slack.com/services/T.../B.../..."

# Run your job and capture the exit code
python3 /home/deploy/scripts/process_orders.py
EXIT_CODE=$?

if [ $EXIT_CODE -ne 0 ]; then
  curl -s -X POST "$SLACK_WEBHOOK" \
    -H "Content-Type: application/json" \
    -d "{\"text\": \"Cron job failed (exit $EXIT_CODE): process_orders.py\"}"
fi

This works. But as soon as you have more than one or two jobs, you'll run into the same problems that come with any direct Slack Webhook setup:

For a single script on a personal project, webhooks are perfectly fine. For a production server with multiple jobs, it becomes a maintenance headache.

Option 2: A Notification API (The Cleaner Way)

Instead of calling Slack directly, you send the alert to a notification API that handles delivery. With NotificationsBot, one API call can reach Slack, Telegram, Discord, or Email — whoever is subscribed to that channel. You manage subscribers in a dashboard, not in your cron scripts.

Shell
curl -s -X POST https://api.notificationsbot.com/event \
  -H "Authorization: Bearer $NOTIFICATIONSBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "cron-alerts",
    "title": "Cron job failed",
    "message": "process_orders.py exited with code 1"
  }'

One API key, one endpoint, all your jobs. If you want to add a team member to the alerts, you add them in the dashboard. No script changes required.

The key difference

With Slack webhooks, your cron scripts are coupled to Slack. With a notification API, your scripts just report what happened and the routing is handled separately. You can add new recipients, switch platforms, or split alerts into channels without touching a single crontab.

Setting Up Slack Alerts with NotificationsBot

If you don't have an account yet, the setup takes about 5 minutes:

From here, any event sent to cron-alerts lands in Slack. You can add more subscribers later — different people, different platforms — without changing your scripts.

A Reusable Shell Wrapper

The cleanest pattern is a small wrapper function you source in every cron script. It runs the job and fires an alert only when it fails, including the exit code and any output.

notify.sh — source this in your cron scripts
#!/bin/bash
# /usr/local/bin/notify.sh

notify_on_failure() {
  local job_name="$1"
  shift
  local output
  output=$("$@" 2>&1)
  local exit_code=$?

  if [ $exit_code -ne 0 ]; then
    local msg="Exit code: $exit_code"
    if [ -n "$output" ]; then
      msg="$msg\n\n$output"
    fi
    curl -s -X POST https://api.notificationsbot.com/event \
      -H "Authorization: Bearer $NOTIFICATIONSBOT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"channel\": \"cron-alerts\",
        \"title\": \"Cron failed: $job_name\",
        \"message\": \"$msg\"
      }"
  fi
  return $exit_code
}

Then your crontab becomes clean and consistent:

crontab
NOTIFICATIONSBOT_API_KEY=your_api_key_here

# Every night at 2 AM — fails silently without the wrapper
0 2 * * * source /usr/local/bin/notify.sh && notify_on_failure "nightly-backup" /home/deploy/scripts/backup.sh

# Every 15 minutes
*/15 * * * * source /usr/local/bin/notify.sh && notify_on_failure "order-sync" python3 /home/deploy/scripts/sync_orders.py

# Every hour
0 * * * * source /usr/local/bin/notify.sh && notify_on_failure "report-generator" node /home/deploy/scripts/generate_reports.js

Python Cron Jobs

If your cron job is a Python script, you can add failure notifications directly in the exception handler:

Python
import os
import sys
import requests
import traceback

API_KEY = os.environ["NOTIFICATIONSBOT_API_KEY"]

def alert_failure(job: str, error: str):
    requests.post(
        "https://api.notificationsbot.com/event",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "channel": "cron-alerts",
            "title": f"Cron failed: {job}",
            "message": error,
        },
        timeout=5,
    )

if __name__ == "__main__":
    try:
        main()
    except Exception:
        alert_failure("process-orders", traceback.format_exc())
        sys.exit(1)

This gives you the full traceback in the Slack message, so you know exactly what failed and where — not just that the job exited with code 1.

Node.js Cron Jobs

Node.js
// run with: node sync_orders.js
async function main() {
  // your cron job logic here
}

async function alertFailure(job, error) {
  await fetch("https://api.notificationsbot.com/event", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NOTIFICATIONSBOT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      channel: "cron-alerts",
      title: `Cron failed: ${job}`,
      message: error.message || String(error),
    }),
  });
}

main().catch(async (err) => {
  await alertFailure("sync-orders", err);
  process.exit(1);
});

Slack Webhooks vs NotificationsBot

Good to know

Only alert on failure, not on every run. A cron job that runs 96 times a day and always succeeds shouldn't generate 96 Slack messages. The wrapper function above already handles this — it stays silent on success and alerts only when something goes wrong.

Bonus: On-Call Escalation

One of the most useful setups for production is having cron failures notify both a Slack channel (for the whole team) and a Telegram subscriber (for the on-call engineer's phone). The team sees the alert in Slack during work hours, and the on-call person gets a personal Telegram ping at 2 AM when the nightly backup fails.

With NotificationsBot, this is just adding two subscribers to the same cron-alerts channel — one Slack, one Telegram. The cron scripts don't change at all.

Never Miss a Failed Cron Job Again

Set up a free account, add a Slack subscriber, and wire up your first cron job alert in under 10 minutes.

Start for free