If you have ever opened GitHub Actions in the morning and realized your scheduled workflow never ran overnight, you already know how frustrating this can be. A GitHub Actions schedule not triggering is not always loud or obvious. There is often no alert, no failure email, and no obvious error message. The workflow just does not run, and the thing it was supposed to do quietly stops happening.
That is a problem if the workflow handles backups, reports, deployments, sync jobs, data cleanup, or any recurring task your app depends on.
The tricky part is that scheduled GitHub Actions workflows can fail before your actual job logic even starts. If the trigger does not fire, your code never runs, your logs stay empty, and traditional debugging gets awkward very quickly.
The problem
A scheduled workflow in GitHub Actions looks simple enough:
on:
schedule:
- cron: '0 * * * *'
You commit it, push it, and expect it to run every hour.
But then it does not.
Maybe it runs irregularly. Maybe it skips a window. Maybe it worked last week and stopped after a small repo change. Maybe it only fails on one repository but works fine on another. In all of these cases, the visible symptom is the same: your automation is missing runs, and you only notice after something downstream breaks.
This is why a GitHub Actions schedule not triggering is more dangerous than a normal failing workflow. With a failing workflow, at least you get a red X and logs. With a missing scheduled trigger, you often get silence.
A few common examples:
- nightly database export never starts
- stale content cleanup stops running
- dependency sync job misses a day
- analytics aggregation silently falls behind
- uptime or health checks stop being generated
If no one is actively looking at the Actions tab, that missed run can sit there for hours or days.
Why it happens
There is no single reason why a GitHub Actions schedule stops triggering. Usually it is one of a handful of platform or configuration issues.
1. The workflow file is not on the default branch
GitHub scheduled workflows run from the default branch only. If your workflow exists only on another branch, the schedule will not fire.
This catches teams all the time during refactors or when they rename branches.
2. The repository has been inactive
GitHub may disable scheduled workflows in public repositories after long periods of inactivity. If nobody notices, the workflow stays disabled and the job simply stops running.
3. The cron expression is valid, but expectations are wrong
GitHub Actions cron uses UTC. A workflow that looks correct can still appear broken if someone expects local time behavior.
For example, if you think this means 9 AM in your own timezone:
- cron: '0 9 * * *'
it actually means 9 AM UTC.
That can look like the workflow is late, early, or missing when it is really just running on a different clock.
4. High-load delays on GitHub's side
GitHub explicitly notes that scheduled workflows are not guaranteed to run at the exact scheduled minute. Delays can happen, especially at busy times like the start of the hour.
So sometimes the issue is not “never triggered,” but “triggered late enough to break your expectations.”
5. The actor or repository state changed
Some scheduled workflows stop behaving as expected after repository ownership changes, permission changes, workflow disabling, or branch changes. These are easy to miss because the YAML itself may still look fine.
6. You are watching failures, not missing executions
A lot of teams only monitor job failure status. That does not help when the workflow trigger never happens at all. In that case there is no failed job to inspect.
That is the core reason this issue keeps slipping through.
Why it's dangerous
A GitHub Actions schedule not triggering is not just an annoying CI problem. It can cause real production damage.
Here are a few realistic outcomes:
- backups stop being created
- generated reports go stale
- recurring data syncs stop updating external systems
- certificate or token maintenance jobs do not run
- cleanup tasks stop, and storage or queues slowly fill up
- deployment automation misses important windows
The business impact is often delayed, which makes it worse.
Nobody notices the skipped run itself. They notice the consequences later, when a customer reports stale data, an internal dashboard looks wrong, or a recovery process fails because the latest backup is missing.
This kind of failure is especially nasty because logs do not help much. If the trigger never fires, there is often nothing new to inspect.
How to detect it
The right way to detect this problem is to monitor for expected execution, not just explicit failure.
That means asking a simple question:
Did this workflow run when it was supposed to?
That is where heartbeat monitoring becomes useful.
Instead of only trusting GitHub’s workflow history UI, you make the workflow send a signal when it starts or finishes. If that signal does not arrive within the expected time window, you alert.
This approach catches all of the cases that ordinary failure alerts miss:
- trigger never fired
- workflow got disabled
- cron expression changed incorrectly
- repository inactivity disabled schedules
- run was delayed too long
- job hung before finishing
The key idea is simple: silence becomes detectable.
Simple solution: use a heartbeat
A practical fix is to make the scheduled workflow send a QuietPulse heartbeat whenever it runs.
The cleanest option for GitHub Actions is to use the QuietPulse action directly:
name: Nightly sync
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run sync
run: ./scripts/sync.sh
- name: Send heartbeat to QuietPulse
if: success()
uses: vadyak/quietpulse-actions@v1
with:
endpoint_token: ${{ secrets.QUIETPULSE_TOKEN }}
Why this works:
- if the workflow runs successfully, QuietPulse receives the expected heartbeat
- if the workflow fails before completion, the heartbeat does not arrive
- if the schedule never triggers at all, the heartbeat also does not arrive
- in all of those cases, a missing expected signal becomes alertable
That is exactly what you want when the real problem is silence.
Curl fallback
If you prefer not to use the GitHub Action, a plain HTTP ping still works:
name: Nightly sync
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run sync
run: ./scripts/sync.sh
- name: Ping QuietPulse
if: success()
run: curl -fsS https://quietpulse.xyz/ping/YOUR_JOB_ID
This is enough to detect a GitHub Actions schedule not triggering, because the expected ping will simply go missing.
The important part is not whether you use the action or curl. The important part is that you monitor expected execution, not just explicit failures.
Common mistakes
1. Assuming GitHub cron is exact to the minute
It is not. Some delay is normal. Build your alert window with a little tolerance.
2. Monitoring only failed runs
This misses the most important case: no run happened at all.
3. Forgetting that cron uses UTC
A lot of “it did not run” reports are actually timezone misunderstandings.
4. Keeping the workflow only on a non-default branch
Scheduled workflows must live on the default branch to run properly.
5. Treating logs as proof that everything is fine
Logs only exist when something actually started. They do not tell you about the run that never happened.
Alternative approaches
There are other ways to deal with scheduled workflow issues, but each has limits.
Checking the Actions UI manually
This works for tiny projects, but it does not scale and depends on someone remembering to look.
Email or GitHub notifications
Useful for explicit failures, but much weaker for missed triggers or delayed schedules.
Log aggregation
Helpful after a run starts. Useless if the workflow never triggered.
Uptime monitoring
Good for APIs and websites, but not for background schedules. A healthy app can still have a dead automation workflow.
Custom audit script against the GitHub API
This can work if you query recent workflow runs and compare timestamps. It is flexible, but now you are building and maintaining monitoring logic yourself.
For most teams, heartbeat monitoring is the simplest option because it focuses on the thing that matters most: whether the job actually ran on time.
FAQ
Why is my GitHub Actions schedule not triggering even though the YAML is correct?
The most common reasons are default branch issues, UTC timezone confusion, repository inactivity disabling schedules, or GitHub-side delays. A valid YAML file does not guarantee an on-time run.
Does GitHub Actions cron always run exactly on schedule?
No. Scheduled workflows can be delayed, especially around busy times. You should allow a grace window instead of assuming exact execution at the scheduled minute.
How do I know if a GitHub scheduled workflow never ran?
The safest method is to send a heartbeat from the workflow and alert when the heartbeat is missing. That detects missed triggers, not just failed jobs.
Should I use curl or the QuietPulse GitHub Action?
Either works. If you want the simplest GitHub-native setup, the QuietPulse action is cleaner. If you want a minimal dependency-free example, curl is fine.
Can logs help debug missing scheduled workflows?
Only partially. Logs help after a workflow starts. If the trigger never fires, there may be no logs at all for the missing run.
Conclusion
A GitHub Actions schedule not triggering is dangerous because it often fails silently. There may be no error, no logs, and no obvious sign that your automation has stopped.
The reliable fix is to stop monitoring only failures and start monitoring expected execution. If your scheduled workflow should run every day, hour, or week, make it send a heartbeat and alert when that heartbeat never arrives. That turns silent misses into something visible before they become real incidents.
Originally published at https://quietpulse.xyz/blog/github-actions-schedule-not-triggering-fix












