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
main or master
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:
- Go to your repository's Actions tab
- Look for a yellow banner saying the workflow has been disabled
- 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 Google3 monitors free. No credit card.
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@weeklyare 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 of0 * * * *) - 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
scheduletrigger 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:
- Go to the Actions tab in your forked repository
- You'll see a message saying workflows are disabled
- 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:
- Trigger manually: Add
workflow_dispatchand run the workflow by hand. If it works manually but not on schedule, the issue is with the schedule trigger specifically. - Check the API: Use
gh run list --workflow=your-workflow.ymlto see recent runs and their statuses. - Review workflow syntax: Run
gh workflow listto confirm GitHub recognizes your workflow file. If it doesn't appear, there's a YAML syntax error. - Check repository settings: Go to Settings → Actions → General and confirm that Actions are enabled and the correct permissions are set.
Related Resources
- Cron Job Not Running — Debug traditional cron jobs that won't execute
- Silent Cron Failures — Detect hidden failures in any cron system
- Cron Timezone Issues — Fix timezone-related scheduling problems
- Monitor GitHub Actions — Full setup guide for GitHub Actions monitoring
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 Google3 monitors free. No credit card required.