Skip to content
Latchkey

GitHub Actions Job Stuck "Waiting for a runner to pick up this job"

A job is queued but no runner ever picks it up. Either no online runner matches every requested label, your self-hosted runner is offline, or you have hit a concurrency or billing limit.

What this error means

The job sits indefinitely with "Waiting for a runner to pick up this job" and never starts. There is no failure, just an unbounded queue wait.

Actions log
Requested labels: self-hosted, gpu, linux
Waiting for a runner to pick up this job...

Diagnose it: is the job queued, or is the runner gone?

A job that never starts and a job whose runner disappeared mid-run look similar in the UI and have opposite causes. The first is a labelling or capacity problem, the second is the runner being killed, usually by memory pressure or a spot reclaim.

.github/workflows/ci.yml
- name: Runner facts
  run: |
    echo "runner name: $RUNNER_NAME"
    echo "os/arch:     $RUNNER_OS/$RUNNER_ARCH"
    nproc; free -h; df -h /
    echo "labels this job asked for: ${{ toJSON(job) }}"

Common causes

No runner matches all requested labels

runs-on requires a runner that carries every label listed. If no online runner has all of them (for example a missing gpu label), the job waits forever.

Self-hosted runner offline or busy

A self-hosted runner that crashed, lost network, or is already running its max jobs cannot accept the queued job.

Out of concurrency or minutes

Hitting the plan concurrency cap, or running out of included minutes/billing, leaves hosted jobs queued until capacity frees up.

How to fix it

Match runs-on to an available runner

Use a label set that an online runner actually carries, or a valid GitHub-hosted label.

.github/workflows/ci.yml
# GitHub-hosted
runs-on: ubuntu-latest
# self-hosted: every label must exist on an online runner
runs-on: [self-hosted, linux, x64]

Bring runners online and check limits

  1. Confirm self-hosted runners show as Idle/Online in repo or org settings.
  2. Check that billing is active and you have not exhausted included minutes.
  3. Verify you are within the concurrent-jobs limit for your plan.

The failures that are not your workflow

  • Exit 137 is the kernel out-of-memory killer, not an application error. Check free -h above against your peak usage.
  • Disk exhaustion presents as unrelated write errors deep in a build. GitHub-hosted runners ship roughly 14 GB of free space, which a Docker-heavy job can exhaust.
  • A lost connection to the server on a self-hosted runner is usually the host being reclaimed or rebooted, not a network fault in your job.
  • A job that starts and immediately fails with no step output normally failed during runner setup, before your workflow ran at all.

How to prevent it

  • Keep runs-on labels in sync with the labels your runners actually register.
  • Monitor self-hosted runner health and auto-restart offline runners.
  • Watch concurrency and minutes usage so jobs do not silently queue.

Frequently asked questions

What causes GitHub Actions job stuck "Waiting for a runner to pick up this job"?
There are 3 common causes: no runner matches all requested labels, self-hosted runner offline or busy, and out of concurrency or minutes. runs-on requires a runner that carries every label listed.
How do I fix GitHub Actions job stuck "Waiting for a runner to pick up this job"?
There are 2 fixes depending on which cause you have: match runs-on to an available runner and bring runners online and check limits. Work through them in order, since the first is the most common.
What does GitHub Actions job stuck "Waiting for a runner to pick up this job" actually mean?
The job sits indefinitely with "Waiting for a runner to pick up this job" and never starts.
How do I stop GitHub Actions job stuck "Waiting for a runner to pick up this job" happening again?
Keep runs-on labels in sync with the labels your runners actually register. The prevention section lists 3 changes that keep it from recurring.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

This is a setup failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card