Originally published on DevToolHub.
A GitHub Actions workflow not triggering almost never means GitHub is broken. It means one of about a dozen rules quietly filtered your event out: the workflow file is on the wrong branch, a filter didn't match, the commit was pushed with GITHUB_TOKEN, or the schedule got disabled. None of these produce an error. The run simply never appears.
This guide covers every reason for a GitHub Actions workflow not triggering, in the order worth checking. Each one comes with the exact rule from GitHub's docs and the fix. If you're still learning workflow syntax, read how GitHub Actions workflow files are structured first.
GitHub Actions Workflow Not Triggering? Quick Diagnosis
Match your symptom to the likely cause, then jump to that section.
| Symptom | Most likely cause |
|---|---|
| No "Run workflow" button |
workflow_dispatch file isn't on the default branch |
| Scheduled workflow never runs | File not on default branch, or auto-disabled after 60 days |
| Scheduled run is late or missing | Queue delay at the top of the hour |
| Push from another workflow triggers nothing | Push used GITHUB_TOKEN
|
| Runs on branches, never on tags |
branches filter defined without tags
|
| Pushed a change, nothing ran |
paths filter didn't match, or [skip ci] in the message |
| Fork PR shows "approval required" | First-time contributor approval |
| Workflow missing from the Actions tab | Invalid YAML, disabled workflow, or Actions turned off |
Before anything else, check whether GitHub created a run at all:
# List recent runs for one workflow, including disabled ones
gh run list --workflow ci.yml --all --limit 10
# Filter by the event you expected
gh run list --workflow ci.yml --event push --branch main
If a run exists with status skipped or action_required, the trigger worked. Something later stopped it. But if there's no run at all, a rule filtered the event out first. That distinction cuts the list below in half.
Workflow Not Triggering Because It's Not on the Default Branch
Many events only fire if the workflow file exists on the default branch. That includes workflow_dispatch, schedule, workflow_run, issues, issue_comment, delete, and most other non-push events. The events reference repeats the same note on each: "This event will only trigger a workflow run if the workflow file exists on the default branch."
This catches people constantly. You add a new workflow_dispatch workflow on a feature branch. Then you open the Actions tab, and there's no "Run workflow" button. The workflow is fine. It just isn't on main yet.
Fix: merge the workflow file to the default branch first. After that, you can dispatch it against any branch:
gh workflow run deploy.yml --ref my-feature-branch -f environment=staging
GitHub's docs spell out the order: the button appears once the file is on the default branch, and once the workflow has run at least once, you can dispatch it against any branch or tag via the API or gh.
⚠️ Note: push and pull_request are the exceptions. They run from the workflow file on the branch you pushed, which is why a CI workflow can work on a feature branch while a new manual workflow can't.
Scheduled GitHub Actions Workflow Not Triggering
Scheduled workflows have four separate failure modes, and none of them show an error.
1. The file isn't on the default branch. Scheduled workflows only run on the default branch, using its latest commit. A cron on any other branch never fires.
2. It was disabled after 60 days. In a public repository, GitHub automatically disables scheduled workflows when there's been no repository activity for 60 days. Forks of public repos also start with scheduled workflows disabled. Re-enable it:
gh workflow list --all # disabled workflows are hidden without --all
gh workflow enable nightly.yml
3. It ran, just late. The docs are blunt about this: schedule events "can be delayed during periods of high loads," the start of every hour is a high-load time, and under enough load "some queued jobs may be dropped." Everyone writes 0 * * * *. Don't.
4. The time is off by hours. Cron runs in UTC unless you say otherwise. GitHub now supports an IANA timezone per schedule, so you can stop converting by hand:
on:
schedule:
- cron: '17 5 * * 1-5' # 5:17 AM, weekdays, off the top of the hour
timezone: "America/New_York"
With a daylight-saving timezone, a run that falls in the skipped spring-forward hour moves to the next valid time. For example, a 2:30 AM schedule runs at 3:00 AM that day. The shortest interval GitHub allows is every 5 minutes.
Why Does a Push From Another Workflow Not Trigger Anything?
Events created with the repository's GITHUB_TOKEN don't start new workflow runs. GitHub does this on purpose to prevent infinite loops. Otherwise, a workflow that pushes a commit would trigger itself forever. The GITHUB_TOKEN docs list the exceptions.
So say your release workflow commits a version bump and pushes it with GITHUB_TOKEN. Your on: push workflow won't run for that commit. There are two exceptions:
-
workflow_dispatchandrepository_dispatchalways create runs, even when sent withGITHUB_TOKEN. - When a workflow opens or updates a pull request with
GITHUB_TOKEN, theopened,synchronizeandreopenedevents create runs in an approval-required state. Someone with write access has to click "Approve workflows to run."
Fix: trigger the next workflow explicitly with workflow_dispatch, or use a GitHub App token or a fine-grained personal access token for the push. The App token is the better choice for shared repos because it isn't tied to a person's account.
Branch, Tag and Path Filters That Silently Skip Runs
Filters are the biggest single reason for a workflow not triggering. Three rules from the workflow syntax reference cause most of it.
Defining branches alone disables tags. If you define only branches/branches-ignore, the workflow won't run for tag pushes, and vice versa. Define neither and it runs for both. So this workflow never runs on v1.2.0:
on:
push:
branches: [main]
# add this to also run on release tags:
tags: ['v*']
branches and paths must both match. When you set both, the workflow runs only when a push matches the branch and changes a matching file. A docs-only commit to main with paths: ['src/**'] does nothing.
Path filters have diff limits. GitHub builds the changed-file list with a two-dot diff for pushes and a three-dot diff for pull requests. So if the diff has more than 3,000 files and your matches aren't in the first 3,000, the workflow won't run. On the other hand, a push with more than 1,000 commits always runs. Large merges and monorepo refactors hit both limits.
⚠️ Important: A workflow skipped by a branch or path filter leaves its required checks stuck in Pending, which blocks the PR from merging. If you require a check that's path-filtered, the usual fix is a small always-running job that reports success when the real job is skipped.
Also note that GitHub won't create push events for tags when more than three tags are pushed at once. Pushing a batch of tags with git push --tags can trigger nothing.
Skip Keywords in the Commit Message
Any of these in the commit message (or the HEAD commit of a PR) stops push and pull_request workflows:
[skip ci][ci skip][no ci][skip actions][actions skip]
A skip-checks: true trailer does the same. This bites teams whose release tooling adds [skip ci] to automated commits. Then someone squash-merges a PR, and the combined message still contains it.
Skip keywords only apply to push and pull_request. They don't stop pull_request_target, schedule or workflow_dispatch.
Pull Requests From Forks Waiting for Approval
When a first-time contributor opens a pull request on a public repository, a maintainer with write access may need to approve the workflow run before it starts. The run exists, with status action_required, but nothing executes until someone approves it on the PR page.
Separately, fork PRs get no secrets except GITHUB_TOKEN, and that token is read-only. That doesn't stop the workflow from triggering, but a deploy step that needs a secret will fail, which is easy to mistake for a trigger problem. Our GitHub Actions security guide covers why pull_request_target is risky as a workaround.
workflow_run Chains That Stop Partway
workflow_run lets one workflow start after another finishes. Two limits cause silent gaps:
- It only fires if the listening workflow is on the default branch (same rule as above).
- You can't chain more than three levels. In GitHub's example, A → B → C → D → E → F runs A through D, and E and F never run.
Also, the requested activity type doesn't fire on re-runs. If you re-run the upstream workflow, a downstream workflow filtered to types: [requested] won't start again. Use completed for most chains.
The Workflow Doesn't Show Up at All
If the workflow is missing from the Actions tab entirely, check these:
-
Location and extension. The file must be in
.github/workflows/with a.ymlor.yamlextension. -
Invalid YAML. A syntax error means GitHub can't parse the triggers. The Actions tab shows the error on the workflow page after you push. Catch it earlier by running
actionlintlocally. -
The workflow is disabled.
gh workflow listhides disabled workflows. Usegh workflow list --all. - Actions is disabled for the repo or org. Check Settings → Actions → General. If you see "GitHub Actions is currently disabled for this repository," GitHub's docs note that changing these settings may not restore access. The account can be in a GitHub-controlled disabled state, which needs support.
GitHub Actions Workflow Not Triggering: The Full Checklist
When you have a GitHub Actions workflow not triggering, work through this in order:
- Does
gh run list --workflow <file> --allshow a run? If yes, check its status instead. - Is the workflow file on the default branch? Required for
schedule,workflow_dispatch, andworkflow_run. - Is the workflow enabled?
gh workflow list --all. - Do
branches,tagsandpathsall match what you pushed? - Did the commit message contain a skip keyword?
- Was the event created with
GITHUB_TOKEN? - Is it a fork PR waiting for approval?
- For schedules: UTC vs your timezone, top-of-the-hour delays, 60-day auto-disable.
Once it runs, make it a required check so it can't be skipped silently. Our unit testing with GitHub Actions guide shows the setup, and the complete Git and GitHub Actions guide ties the whole workflow together.
Frequently Asked Questions
Q: Why doesn't my workflow_dispatch workflow show a Run workflow button?
A: The workflow file isn't on the default branch yet. GitHub only shows the "Run workflow" button when the file exists on the default branch. Merge it to main, then you can dispatch it against any branch with gh workflow run <file> --ref <branch>.
Q: Why is my GitHub Actions cron schedule not running?
A: Scheduled workflows only run from the default branch, run in UTC unless you set a timezone, can be delayed or dropped at the top of the hour, and are auto-disabled in public repos after 60 days without activity. Check gh workflow list --all to see if it's disabled.
Q: Why doesn't a commit pushed by a workflow trigger other workflows?
A: Events created with the repository's GITHUB_TOKEN don't start new workflow runs, to prevent recursive loops. Use workflow_dispatch or repository_dispatch to chain workflows, or push with a GitHub App token instead.
Q: Why does my workflow run on branches but not on tags?
A: If you define only a branches filter under push, GitHub won't run the workflow for tag pushes. Add a tags filter, such as tags: ['v*'], to cover both.
Q: Why are my required checks stuck in Pending?
A: A workflow skipped by a path filter, branch filter or skip keyword leaves its checks pending, which blocks merging. Add a job that always runs and reports success, or avoid path-filtering required checks.
Quick Summary:
-
schedule,workflow_dispatchandworkflow_runonly fire when the workflow file is on the default branch - Pushes made with
GITHUB_TOKENdon't start new runs, exceptworkflow_dispatchandrepository_dispatch - A
branches-only filter silently ignores tag pushes, andbranches+pathsmust both match - Public-repo schedules auto-disable after 60 days of inactivity and can be delayed at the top of the hour
- Scheduled workflows accept an IANA
timezone, so you no longer have to convert cron times to UTC by hand
Next time you're stuck with a GitHub Actions workflow not triggering, start with gh run list --workflow <file> --all. Whether a run exists tells you which half of this list to check.
Top comments (0)