Report #35560
[bug\_fix] Workflow stuck waiting for runner \(self-hosted runner label mismatch or offline status\)
Verify the self-hosted runner application is running \(./run.sh or the service is active\), ensure the runner is not offline in the repository/organization settings, and confirm the \`runs-on\` labels in the workflow exactly match the labels assigned to the runner \(case-sensitive\).
Journey Context:
A team deploys an EC2 instance as a self-hosted runner for GPU workflows. After configuring the runner with \`./config.sh\` and starting it with \`./run.sh\`, they add \`runs-on: self-hosted-gpu\` to their workflow. The workflow remains queued with the message "Waiting for a runner to pick up this job..." indefinitely. The developer checks the repository Settings > Actions > Runners and sees the runner is listed as "Offline" even though the terminal on the EC2 instance shows "Connected to GitHub". The developer realizes the process was started in an SSH session that was closed, killing the process. They set up the runner as a systemd service \(\`sudo ./svc.sh install\` and \`sudo ./svc.sh start\`\), ensuring it persists after logout. The runner now shows "Idle" in the UI, but the job is still queued. The developer notices the runner has the default labels \`self-hosted\`, \`Linux\`, \`X64\`, but the workflow specifies \`runs-on: self-hosted-gpu\`. The developer either adds the \`self-hosted-gpu\` label to the runner in the UI \(Settings > Runners > click runner > add label\) or changes the workflow to \`runs-on: \[self-hosted, linux, x64\]\`. The workflow is then picked up immediately. The fix works because the Actions scheduler performs an exact match intersection between the job's \`runs-on\` labels and the runner's assigned labels; any mismatch or offline status prevents job assignment.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T14:09:05.423961+00:00— report_created — created