Vivere

Vivere / Answers

GitHub Actions scheduled workflow stopped running: how to find out why

A scheduled workflow that stops is almost always switched off by GitHub or never scheduled, not broken. Three commands tell you which of seven causes it was, and each has its own fix.

A workflow with a schedule trigger that ran every night and now does not is usually not broken. In most cases GitHub has stopped scheduling it on purpose, or never scheduled the version of the file you are looking at. Nothing fails, so nothing in GitHub tells you, and the first sign is often a report or a backup that is weeks old.

Everything below was checked against GitHub's documentation for the schedule event in October 2026.

First, find out which one it was

Three commands with the GitHub CLI, run inside a clone of the repository, narrow it down in a minute. The workflow's state:

gh workflow list --all --json name,path,state

The state is one of active, disabled_inactivity, disabled_manually, disabled_fork or deleted, the same values the REST API returns. The scheduled runs that actually happened, newest first:

gh run list --all --workflow nightly.yml --event schedule --limit 30 \
  --json createdAt,conclusion,headBranch

And the branch GitHub schedules from:

gh api repos/{owner}/{repo} --jq .default_branch

Then read the answer off this list:

1. Disabled after 60 days without activity

GitHub's documentation says that in a public repository, scheduled workflows are automatically disabled when no repository activity has occurred in 60 days. The workflow file stays where it is; GitHub stops starting it. A repository whose only job is to run something on a schedule hits this every two months unless somebody commits to it.

The Actions tab shows a banner on a workflow disabled this way. To turn it back on, open the workflow in the Actions tab and press Enable workflow, or:

gh workflow enable nightly.yml

A commit that changes the workflow's cron line also reactivates it, if the person who commits has write access; GitHub then makes that person the workflow's actor. GitHub's page on disabling and enabling workflows covers the button and the CLI. Turning it back on is the easy part; keeping a scheduled workflow from being disabled after 60 days covers the options and what each one costs.

2. The schedule only runs from the default branch

The schedule event only triggers a workflow if the workflow file exists on the default branch, and the run uses the latest commit on that branch. A cron trigger added on a feature branch is never scheduled, however correct the YAML is, and an edit to the cron line on a branch changes nothing until it is merged. Changing the default branch changes which copy of the file GitHub reads, so a rename from master to main, or a new default branch that does not have the workflow, can stop a schedule overnight. Cron not triggering on a branch or a fork goes through it, including how to test a schedule before merging it.

3. It is a fork

When a public repository is forked, scheduled workflows are disabled by default in the fork. The upstream repository's schedule keeps running; the fork's copy does nothing until somebody enables Actions in the fork and then the workflow itself. A fork is also a public repository in its own right, so the 60-day rule applies to it as well.

4. Delayed, or dropped, at busy times

GitHub's documentation says the schedule event can be delayed during periods of high load, that the start of every hour is a high-load time, and that if the load is high enough some queued jobs may be dropped. A run that was dropped leaves no trace: no failed run, no skipped run, just a gap in the run history. The fix GitHub suggests is to schedule at a different time of the hour, so 17 3 * * * rather than 0 3 * * *. Scheduled workflow runs late or is skipped shows how to measure the delay from your own run history and what to do when a job cannot be late.

5. The edit that quietly removed the schedule

A workflow edited for another reason can lose its schedule without anybody meaning to. Things to check in the file on the default branch:

actionlint, a linter for workflow files, checks the cron syntax and the timezone string, and catches most of these before they are merged.

6. Billing, or Actions turned off

In a private repository, GitHub-hosted runners use the account's included minutes. GitHub's billing page says that if the account has no valid payment method, usage is blocked once the quota is used up, and with a payment method, budgets may limit spending. Public repositories on standard GitHub-hosted runners, and self-hosted runners, are free. Actions can also be turned off for a repository or a whole organization under Settings, Actions, General, which stops every workflow, scheduled ones included.

7. It ran, and did nothing

If scheduled runs appear and succeed but the work did not happen, look for steps skipped by an if: condition written for another trigger. A step with if: github.event_name == 'push' is skipped on a scheduled run, and the job still reports success. A workflow with several schedule entries can tell them apart through github.event.schedule, and a condition that compares it with a cron string that was later edited skips the step for good.

It is also worth knowing who GitHub tells when a scheduled run fails. GitHub's notification rules send those notifications to the user who created the workflow, or to whoever last changed its cron syntax, or to whoever re-enabled it after it was disabled. If that person has left, or filters Actions mail, a failing scheduled workflow can fail every night with nobody reading about it.

How to notice next time

Every cause above except the last is silent: there is no failed run to be notified about, because there is no run. The way to hear about a run that did not happen is to have every run report to something outside GitHub, and to be alerted when the report does not arrive. Getting an alert when a scheduled workflow does not run compares the ways of doing that, including a watchdog workflow inside GitHub and where it falls short.

With Vivere it is a monitor and two steps from the Vivere ping action on the GitHub Marketplace. Create a heartbeat monitor with the same cron expression and timezone as the workflow, put its ping URL in a repository secret named VIVERE_PING_URL, and add the action at the start and the end of the job:

name: Nightly export
on:
  schedule:
    - cron: "17 3 * * *"
      timezone: "Europe/London"
  workflow_dispatch:

jobs:
  export:
    runs-on: ubuntu-latest
    steps:
      - uses: nicholasbergesen/vivere-ping-action@v1
        with:
          url: ${{ secrets.VIVERE_PING_URL }}
          status: start

      - uses: actions/checkout@v7
      - run: ./scripts/export.sh

      - uses: nicholasbergesen/vivere-ping-action@v1
        if: always()
        with:
          url: ${{ secrets.VIVERE_PING_URL }}
          status: ${{ job.status }}

The first step opens a run so Vivere records how long the job took. The last runs whatever happened before it and passes on job.status: a success closes the run, and a failure or a cancellation alerts at once. If the workflow is disabled, dropped at a busy hour, or never scheduled at all, no ping arrives, and the monitor alerts when its grace period runs out. Set the grace to the latest you have seen this workflow start plus its longest normal run; the grace period calculator works it out.

Vivere's free plan covers 25 monitors with email and webhook alerts; paid plans add Slack, Discord, Telegram and ntfy. The GitHub Actions guide has the plain curl version for anyone who would rather not add an action.

Common questions

Why did my GitHub Actions scheduled workflow stop?

In a public repository, GitHub automatically disables scheduled workflows when no repository activity has occurred in 60 days. That is the most common cause. The others are a workflow file that is not on the default branch, a fork (forks of public repositories start with scheduled workflows disabled), a workflow disabled by hand, a schedule lost in an edit, runs delayed or dropped at busy times, and a private repository's Actions quota running out. gh workflow list --all --json name,state shows which state the workflow is in.

How do I re-enable a scheduled workflow GitHub disabled?

Open the workflow in the repository's Actions tab and press Enable workflow, or run gh workflow enable followed by the workflow's file name. A commit that changes the workflow's cron line, made by someone with write access, also reactivates it. Runs that were due while it was disabled do not happen later.

Does a GitHub Actions schedule run on a branch other than the default?

No. The schedule event only triggers a workflow if the file exists on the default branch, and the run uses the latest commit on that branch. A cron trigger on a feature branch is never scheduled, and an edit to the cron line on a branch has no effect until it is merged.

What timezone does a GitHub Actions schedule use?

UTC by default. A schedule entry can set timezone to an IANA name such as America/New_York. With a timezone that observes daylight saving, a run due in the hour skipped in spring moves to the next valid time.

Find out without looking

Vivere watches for the ping that does not arrive. Add one line to the job, pick where alerts should land, and you hear about the run that never happened.

Start free Read the quickstart

25 monitors, a status page, email and webhook alerts. No card.

Last reviewed October 2026.

Related