Troubleshooting Guide

GitHub Actions Cron Not Running? Here's How to Fix It

Your scheduled GitHub Actions workflow should be triggering, but it's not. Let's figure out why and fix it.

Quick Diagnostic Checklist

Is the workflow file on the default branch? Schedules only run from main or master
Has the repo been inactive for 60+ days? GitHub auto-disables scheduled workflows
Is the cron syntax valid? Must be 5-field POSIX cron (no seconds)
Check the Actions tab for recent runs Look for disabled workflow warnings

GitHub Actions schedule triggers behave differently from traditional cron. Several platform-specific quirks can silently prevent your workflow from running. Here are the most common causes and how to fix each one.

1. Repository Inactivity Disables Scheduled Workflows

This is the most common reason GitHub Actions cron stops working, and the one that catches people off guard.

GitHub automatically disables scheduled workflows on any repository that has had no activity for 60 days. "Activity" means commits, issues, pull requests, or other repository events. Simply having the workflow run on schedule does not count as activity.

When this happens, GitHub sends an email notification — but it's easy to miss. The workflow silently stops running with no error in the Actions tab.

How to check:

  1. Go to your repository's Actions tab
  2. Look for a yellow banner saying the workflow has been disabled
  3. Click Enable workflow to re-activate it

How to prevent it:

  • Make at least one commit or open an issue every 60 days
  • Use a separate workflow that creates a lightweight commit or issue to keep the repo active (though GitHub may close this loophole)
  • Monitor the workflow externally so you're alerted when it stops running (more on this below)
If your workflow ran fine for months and then suddenly stopped, this is almost certainly the cause.

Fixed it? Make sure it stays fixed — get alerted if this workflow stops running.

Sign up with Google
or

2. Cron Syntax Differences in GitHub Actions

GitHub Actions uses POSIX cron syntax with 5 fields only:

# ┌───────────── minute (0-59)
# │ ┌───────────── hour (0-23)
# │ │ ┌───────────── day of month (1-31)
# │ │ │ ┌───────────── month (1-12)
# │ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
# │ │ │ │ │
# * * * * *

Common mistakes:

  • Using 6 fields (with seconds): Some cron systems support a seconds field. GitHub Actions does not. 0 */5 * * * * is invalid — use */5 * * * * instead.
  • Using non-standard syntax: Expressions like @hourly, @daily, or @weekly are not supported in GitHub Actions. You must use the 5-field format.
  • Quoting issues in YAML: The cron expression must be quoted in your workflow file. An unquoted * can break YAML parsing.

Correct format in your workflow file:

on:
  schedule:
    - cron: '30 2 * * 1-5'  # Weekdays at 2:30 AM UTC

Note that all scheduled times are in UTC. There's no way to set a timezone for the schedule trigger itself. If you need timezone-aware scheduling, you'll need to add a conditional check inside your workflow.

Use our cron expression validator to verify your syntax before committing.

3. Schedule Delays and Skipped Runs

GitHub Actions does not guarantee exact timing for scheduled workflows. This is documented behavior, not a bug.

What to expect:

  • During normal load, runs typically start within 1-5 minutes of the scheduled time
  • During peak load (top of the hour, midnight UTC), delays of 10-30 minutes are common
  • In extreme cases, scheduled runs can be skipped entirely with no notification
  • The shortest recommended interval is */5 * * * * (every 5 minutes), but even this may experience missed runs

If you check the Actions tab and see gaps in your run history, this is likely the cause. GitHub prioritizes event-driven workflows (push, pull_request) over scheduled ones during periods of high demand.

What you can do:

  • Don't rely on exact timing for critical tasks — build your job to be idempotent
  • Avoid scheduling at the top of the hour (e.g., use 23 * * * * instead of 0 * * * *)
  • Use external monitoring to detect when runs are skipped

4. Workflow Must Be on the Default Branch

Scheduled workflows only trigger from the default branch of your repository (usually main or master). This is a common source of confusion during development.

If you:

  • Create a new workflow with a schedule trigger on a feature branch — it won't run
  • Modify the cron schedule on a feature branch — the old schedule from the default branch continues to run
  • Delete the workflow from the default branch — the schedule stops immediately

The fix: Merge your workflow file to the default branch. The schedule will only activate after the merge.

To test a scheduled workflow before merging, use workflow_dispatch to trigger it manually:

on:
  schedule:
    - cron: '0 2 * * *'
  workflow_dispatch:  # Allows manual triggering for testing

Then click "Run workflow" from the Actions tab while on your feature branch.

5. Forks Don't Run Scheduled Workflows

If you forked a repository, scheduled workflows are disabled by default. This is a security measure — GitHub doesn't want forks automatically running potentially untrusted code on a schedule.

To enable scheduled workflows on a fork:

  1. Go to the Actions tab in your forked repository
  2. You'll see a message saying workflows are disabled
  3. Click I understand my workflows, go ahead and enable them

Even after enabling, the workflow needs to be on your fork's default branch to run on schedule.

6. How to Prevent Silent Failures

The fundamental problem with GitHub Actions scheduled workflows is that you get no notification when things go wrong. When GitHub disables your workflow due to inactivity, delays a run, or skips one entirely, there's no alert in the Actions tab. You only find out when you check manually — or when something downstream breaks.

The solution is external monitoring. Add a heartbeat ping to your workflow that fires on every run. If the ping doesn't arrive on schedule, you get alerted immediately.

Add the CronSignal ping action to your workflow:

jobs:
  my-scheduled-job:
    runs-on: ubuntu-latest
    steps:
      - name: Your actual work
        run: echo "Running scheduled task..."

      - name: Ping CronSignal
        if: always()
        uses: CronSignal/ping-action@v1
        env:
          JOB_STATUS: ${{ job.status }}
        with:
          check-id: ${{ secrets.CRONSIGNAL_CHECK_ID }}
          ping-on-failure: fail

The if: always() ensures the ping step runs regardless of whether previous steps succeeded or failed. The ping-on-failure: fail option sends a failure signal to CronSignal when the job fails, so you get different alerts for "job didn't run" vs "job ran but failed."

This catches every GitHub Actions-specific failure mode:

  • Workflow disabled due to inactivity — no ping, you get alerted
  • Scheduled run skipped during high load — no ping, you get alerted
  • Workflow runs but your job fails — failure ping, you get alerted
  • Repository deleted or workflow file removed — no ping, you get alerted

Get the action from the GitHub Marketplace, or read the full GitHub Actions monitoring guide for setup details.


Quick Reference: Debugging Steps

If your scheduled workflow still isn't running after checking the above, try this:

  1. Trigger manually: Add workflow_dispatch and run the workflow by hand. If it works manually but not on schedule, the issue is with the schedule trigger specifically.
  2. Check the API: Use gh run list --workflow=your-workflow.yml to see recent runs and their statuses.
  3. Review workflow syntax: Run gh workflow list to confirm GitHub recognizes your workflow file. If it doesn't appear, there's a YAML syntax error.
  4. Check repository settings: Go to Settings → Actions → General and confirm that Actions are enabled and the correct permissions are set.

Related Resources

Stop wondering if your GitHub Actions cron is running

CronSignal alerts you the moment a scheduled workflow doesn't run. No ping = you get notified. Works with any CI/CD system.

Sign up with Google
or