October 8, 2026 · 6 min read
The GitHub Actions workflow that quietly stopped running
A scheduled GitHub Actions workflow can stop running and leave nothing behind to look at. No red X, because there is no run. No email, the YAML untouched, the cron expression still valid, git log clean. GitHub disabled it, and the only record of that is a toggle nobody opens.
The usual cause is not a bug in the workflow. It is a GitHub policy you agreed to by never reading it.
Repositories go quiet, and so do their schedules
GitHub automatically disables a scheduled workflow once a repository has gone 60 days without a commit. This is a resource-saving default, not a mistake, and it is documented, but nothing about the repository looks different afterward. The workflow file is still there. The cron expression is still valid. There is no issue, no notification, and no line in the Actions log, because a disabled workflow does not run at all, so it never gets the chance to fail loudly.
The workflows I have lost this way were all low-churn: a dependency-update workflow, a backup script, a link checker, anything scheduled in a repo that otherwise sees a commit every few months. The very quietness that made the repo a fine candidate for an unattended cron job is what trips the 60-day clock. And once it fires, a push does not automatically flip the workflow back on. Someone has to open the Actions tab, find the workflow, and click Enable workflow by hand.
Even a live schedule is best-effort
Separately from the 60-day rule, even a live schedule is not exact. GitHub is explicit that scheduled runs are not guaranteed to fire at the exact minute. “The schedule event can be delayed during periods of high loads.” The top of every hour is the worst offender, since every cron-on-earth-adjacent CI job wants to run at 0 * * * *. A short-interval schedule (every 5 or 10 minutes) is the most exposed. A delayed or dropped tick is a bigger fraction of the expected cadence, and it is easy to mistake for the workflow being broken when it is only late.
There is one more trap. Scheduled workflows run on the latest commit on the default branch and nowhere else. A schedule added on a feature branch, or one left behind after the default branch changes, never fires, silently, forever.
The Actions tab is not a monitor
All three failure modes share a shape. The absence of a run produces no signal inside GitHub itself. I do not open the Actions tab of a job that is supposed to just work, not until the day I need something it was supposed to have produced. The fix is the same one that applies to any scheduled job. Have the run report itself to something outside GitHub, and alert on the report going missing.
name: Nightly export
on:
schedule:
- cron: "17 3 * * *" # an odd minute, not :00 - avoids the top-of-hour pile-up
workflow_dispatch: {}
jobs:
export:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/export.sh
- name: Ping illari
if: always()
run: |
curl -fsS -m 10 "https://illari.dev/ping/YOUR_KEY/${{ job.status == 'success' && 0 || 1 }}"if: always() is doing the real work here. The ping step runs whether the export step passed or failed, so a broken export still reports in with a non-zero code instead of silently not pinging at all. A monitor with no fixed schedule (open-ended, alert if silent for N hours) sidesteps the exact-minute question entirely. It does not care whether the run landed at 03:17 or twenty minutes later under load, only that it landed within the window you set.
A workflow file that has not changed in months is not proof it is still running. The only proof is a report from the run itself, sent somewhere that notices when the reports stop.
Monitor a scheduled job with illari
Your job pings a URL when it runs. Miss the window and you get an alert. 25 monitors free, no credit card.