← Actions Runner Starvation Check
Re-running the failed job is most people's first move on a red check, and it is a reasonable one -- if the job actually ran and hit a genuinely flaky test, a re-run can pass and confirm that. What it costs is a full run's worth of time, and during a starvation window it is often uninformative: a job that never got a runner the first time has no more claim on one the second time, so the same push can burn several retries before the pattern -- runner_id: 0 every single time -- becomes obvious.
This tool answers from the JSON the very first failed run already produced, before you spend a second run finding out. It reads the one field the checks tab never shows you and tells you in one click whether a runner was ever assigned.
| Question | Where to answer it |
|---|---|
| The job ran and I suspect a flaky test -- will it pass if I try again? | Re-run the job -- that is a real question about test flakiness this tool does not answer. |
| Did this job even get a runner the first time? | This checker -- reads runner_id from the JSON you already have, no second run needed. |
| Six checks went red in three seconds on a change that couldn't break them all. | This checker -- that pattern is the starvation signature; paste the JSON and confirm it instantly instead of guessing from how it looks. |
| I want this decided automatically in CI, without a person reading the checks tab. | python3 check.py --run RUN_ID -- exits 1 the moment any job was starved, wireable into a workflow step. |
Used together: re-run when you have a specific reason to suspect flakiness in a job that actually executed; reach for this tool first when several unrelated checks all went red at once, or before spending a retry on a job that may never get a runner anyway.
Paste the same JSON you would check before deciding to re-run anything.
Free, runs entirely in your browser, nothing is uploaded. If the verdict is starved, actions-minutes-estimator projects which workflow is spending the allowance before the next run goes the same way.
It is the obvious move, and it is not wrong -- if the job actually ran and hit a flaky test, a re-run can genuinely pass and tell you something. It is just slow and, during a starvation window, uninformative: a job that never got a runner the first time has no more reason to get one the second time, so the same push can burn several retries before anyone notices the pattern is runner_id: 0 every time, not a flaky assertion.
Only after the fact and only sometimes -- if a runner happens to be available on a later retry, the job passes and you never learn why it failed the first time; if runners are still starved, it fails again and looks like a flaky or broken job either way. This tool answers from the very first run's own JSON, before you spend a second run finding out.
The run's own runner_id field, which the checks tab never surfaces. A job that was actually scheduled has a real, nonzero id; a job GitHub never got to has runner_id: 0 and an empty runner_name. That single field is proof no step could have run, and it is present on the very first failed run -- a re-run does not reveal it any better, it just spends another run's worth of time.
No. You fetch it yourself with your own gh CLI or token, paste it into this page, and the verdict is computed in your browser. Nothing about your run, your repository, or your token is sent anywhere -- the only network request in the whole flow is the one you made yourself to GitHub's API.