Report #75874
[bug\_fix] Workflow stuck waiting for self-hosted runner with specific labels that appears offline or idle
Ensure the self-hosted runner service is running \(check with \`sudo ./svc.sh status\` on Linux/macOS or Services panel on Windows\), verify network connectivity to GitHub, and confirm the runner's assigned labels exactly match the workflow's \`runs-on\` labels including case sensitivity.
Journey Context:
You configure a workflow with \`runs-on: \[self-hosted, linux, x64, gpu\]\` to run tests on your specialized machine with a GPU. You push a commit, but the workflow job stays in a "Queued" state indefinitely with the message "Waiting for a runner to pick up this job..." or "Requested labels: self-hosted, linux, x64, gpu". You check your self-hosted runner machine and see the \`run.sh\` script is still running in your terminal showing "Connected to GitHub". However, looking at the repository Settings > Actions > Runners, your runner shows as "Idle" but the job never assigns. You check the runner labels in the UI and see "self-hosted, Linux, X64" but you notice your workflow specifies \`gpu\` and the runner doesn't have that label. You try removing \`gpu\` from the workflow, but it still doesn't pick up. You then disconnect your SSH session and the runner goes offline entirely. You realize you were running \`./run.sh\` interactively, which stops when you log out. The debugging involves checking the \`\_diag/\` log files on the runner machine to see if it's receiving job requests \(it isn't\), confirming network firewalls allow HTTPS to GitHub, and verifying label case sensitivity \(Linux vs linux\). The fix is to first install the runner as a persistent service using \`sudo ./svc.sh install\` and \`sudo ./svc.sh start\` \(on Linux/macOS\) or using the Windows Service manager, ensuring it survives logouts. Then, ensure the runner's labels configured during \`./config.sh\` exactly match the workflow's \`runs-on\` array, adding any missing labels like \`gpu\` via \`./config.sh --labels\` if needed. This works because the runner only picks up jobs where the runs-on labels are a subset of the runner's assigned labels, and the service must be running persistently to poll GitHub for jobs.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T09:56:44.534566+00:00— report_created — created