GitLab CI Error Guide: 'This job is stuck because the project doesn't have any runners online' Stuck Pending Jobs
Fix GitLab CI jobs stuck with no runners online: register a runner, restore offline or paused runners, match job tags, enable shared runners, and clear busy concurrency.
- #gitlab-cicd
- #troubleshooting
- #errors
- #runners
Overview
When a GitLab pipeline job sits in pending and never starts, GitLab is telling you it cannot find a runner willing and able to pick it up. The job is queued, but no online runner is assigned to the project, no runner matches the job’s tags, or every eligible runner is paused, offline, or busy. The pipeline does not fail — it just hangs, which makes this one of the more confusing CI/CD stalls to triage.
The message in the job view is explicit about which flavour of the problem you have hit:
This job is stuck because the project doesn't have any runners online assigned to it.
Go to project CI/CD settings
A tag mismatch produces a different, equally literal variant — note that it lists the exact tags the job is asking for:
This job is stuck because you don't have any active runners online or available with any of these tags assigned to them: docker.
The status code is fixed (pending); the cause varies. It is almost always a problem with the runner — its registration, its service, its tags, or its availability — not with your .gitlab-ci.yml logic.
Symptoms
- A job shows the “stuck” warning icon and stays in
pendingindefinitely while the pipeline reports as running. - The job log is empty and the only text is “This job is stuck because…”.
- Settings > CI/CD > Runners shows no green (online) runner, or shows a runner with a grey/paused badge.
- A previously working pipeline stalls after a runner host reboot, a token rotation, or a tag change in
.gitlab-ci.yml. - Shared/instance runners disappeared after someone toggled them off for the project or group.
glab ci status
Pipeline #84213 (running) for branch feature/api-cache
build pending This job is stuck because the project doesn't have any runners online assigned to it.
sudo gitlab-runner verify
Verifying runner... is alive runner=8e2f1ab3
ERROR: Verifying runner... is removed runner=4c91de77
A runner that verifies as removed was deleted on the GitLab side but still sits in config.toml, so it never picks up jobs.
Common Root Causes
1. No runner is registered or assigned to the project
A brand-new project (especially self-managed without shared runners) has zero runners attached. Nothing is listening for its jobs.
# Self-managed: list runners assigned to the project via the API
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42/runners" | jq '.[].description'
[]
This job is stuck because the project doesn't have any runners online assigned to it.
An empty array means no runner is bound to the project. Register one, or enable shared/group runners (see #5).
2. The runner is paused or offline (not heartbeating)
A registered runner that stopped sending its contact heartbeat goes offline; an admin can also explicitly pause it. Either way it is invisible to the scheduler.
sudo gitlab-runner list
sudo systemctl status gitlab-runner
Runner gitlab-runner
docker-1 Executor=docker Token=glrt-xxxx URL=https://gitlab.example.com
● gitlab-runner.service - GitLab Runner
Active: inactive (dead) since Mon 2026-06-22 03:11:04 UTC
This job is stuck because the project doesn't have any runners online assigned to it.
The service is dead, so the runner never checked in and GitLab marks it offline. A paused runner shows a paused badge in Settings > CI/CD > Runners even while the service is up.
3. The job has a tag no runner matches (or the runner won’t run untagged jobs)
GitLab only schedules a job on a runner whose tag set is a superset of the job’s tags:. If your job asks for docker but no online runner carries that tag, it stays stuck.
# .gitlab-ci.yml — this job demands a 'docker' runner
build:
stage: build
tags:
- docker
script:
- docker build -t app .
This job is stuck because you don't have any active runners online or available with any of these tags assigned to them: docker.
The mirror image: a job with no tags: only runs on a runner that has “Run untagged jobs” enabled. If every runner is tag-restricted, untagged jobs hang too.
4. The runner is registered but not actually running as a service
Registration writes config.toml, but if the gitlab-runner process is not running (or was started under the wrong user), nothing polls GitLab for work. A failed or expired registration token leaves you with no runner at all.
sudo gitlab-runner status
sudo journalctl -u gitlab-runner --no-pager | tail -20
gitlab-runner: Service is not running.
# or, on a fresh register with a bad token:
ERROR: Registering runner... failed runner=glrt-xxxx status=403 Forbidden
PANIC: Failed to register the runner.
This job is stuck because the project doesn't have any runners online assigned to it.
Re-run registration with a valid token, then start the service:
sudo gitlab-runner register --url https://gitlab.example.com --token glrt-REALTOKEN
sudo gitlab-runner start
5. Shared/group runners are disabled for the project
Instance (“shared”) runners and group runners can be toggled off per project. If a project relies on them and someone disabled them — or “Enable shared runners for this project” is off — the project has no runners even though the instance has plenty.
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42" | jq '{shared_runners_enabled, group_runners_enabled}'
{
"shared_runners_enabled": false,
"group_runners_enabled": false
}
This job is stuck because the project doesn't have any runners online assigned to it.
Re-enable them in Settings > CI/CD > Runners (toggle “Enable shared runners for this project”) or via the API by patching shared_runners_enabled=true.
6. All runners are busy or the runner is protected-branch-only
A runner caps how many jobs it runs at once via concurrent and limit in config.toml. When that ceiling is reached, new jobs queue behind the busy ones and read as stuck. Separately, a runner flagged “Run untagged jobs” off / protected only refuses jobs on unprotected branches.
grep -E 'concurrent|limit' /etc/gitlab-runner/config.toml
concurrent = 1
[[runners]]
limit = 1
This job is stuck because the project doesn't have any runners online assigned to it.
With concurrent = 1 and one long-running job, everything else waits. Raise concurrent/limit, or uncheck “Protected” if the branch is not protected.
Diagnostic Workflow
Step 1: Read the exact stuck message and note the tags
glab ci status
The wording tells you the branch of the problem: “doesn’t have any runners online assigned to it” means no eligible runner exists; “with any of these tags assigned to them: X” means a tag mismatch. The named tag is the one your .gitlab-ci.yml job is requesting.
Step 2: Check whether any runner is online for the project
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42/runners" | jq '.[] | {description, online, paused, tag_list}'
An empty result means no runner is assigned (go to Step 5). If runners exist but online: false or paused: true, the problem is availability (Step 3). If they are online but the tags do not include the job’s tag, it is a tag mismatch (Step 4).
Step 3: Verify the runner service is alive and heartbeating
sudo gitlab-runner status
sudo gitlab-runner verify
sudo journalctl -u gitlab-runner --no-pager | tail -30
Service is not running or a verify result of is removed explains an offline runner. Start it with sudo gitlab-runner start and confirm the badge turns green in the UI.
Step 4: Compare job tags against runner tags
grep -A2 'tags:' .gitlab-ci.yml
sudo gitlab-runner list # then read tag_list from the API in Step 2
Either add the missing tag to the runner, remove the tags: from the job, or enable “Run untagged jobs” on the runner so it can pick up untagged work.
Step 5: Confirm registration and shared-runner settings
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42" | jq '{shared_runners_enabled, group_runners_enabled}'
sudo gitlab-runner register --url https://gitlab.example.com --token glrt-REALTOKEN
If no runner is bound, register one and/or flip shared runners back on. After any change, retry the pipeline and watch the runner badge go green.
Example Root Cause Analysis
After a maintenance reboot of the CI host, every new pipeline on gitlab.example.com hangs. The first job stays pending and shows the stuck warning.
The job view names the problem:
This job is stuck because the project doesn't have any runners online assigned to it.
The project does have a registered runner, so this looks wrong — until you check the runner host:
sudo gitlab-runner status
sudo systemctl is-enabled gitlab-runner
gitlab-runner: Service is not running.
disabled
The service was never enabled, so it did not come back after the reboot. With the daemon down, the runner stopped heartbeating, GitLab marked it offline, and the project effectively had zero online runners.
Confirm from the API side that the runner is registered but offline:
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42/runners" | jq '.[] | {description, online}'
{ "description": "docker-1", "online": false }
Fix: start the service, enable it so it survives the next reboot, and verify it checks in:
sudo gitlab-runner start
sudo systemctl enable gitlab-runner
sudo gitlab-runner verify
Verifying runner... is alive runner=8e2f1ab3
Within a few seconds the runner badge turns green in Settings > CI/CD > Runners, the stuck job picks up, and the pipeline runs.
Prevention Best Practices
- Run
sudo systemctl enable gitlab-runnerat provisioning time so the runner daemon always comes back after a reboot instead of silently leaving the project with no online runners. - Keep a documented mapping between the
tags:your jobs use and the tags your runners carry, and review it whenever you add a new executor or job type. - Decide deliberately whether each runner should “Run untagged jobs,” and make sure at least one online runner can pick up untagged work.
- Alert on runner availability (a quick
gitlab-runner verifycron, or watchingonline/pausedvia the API) so an offline runner is caught before it stalls a release. - Treat registration-token rotation as a change that requires re-registering and restarting runners, and confirm
gitlab-runner listplus a green badge afterward. - For fast triage of a stuck-pipeline storm, the free incident assistant can read the stuck message and point at the likely runner cause. More pipeline fixes live in the GitLab CI/CD guides.
Quick Command Reference
# Read the stuck message and pipeline state
glab ci status
# List runners assigned to the project (online/paused/tags)
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42/runners" | jq '.[] | {description, online, paused, tag_list}'
# Is the runner service alive and registered?
sudo gitlab-runner status
sudo gitlab-runner list
sudo gitlab-runner verify
sudo journalctl -u gitlab-runner --no-pager | tail -30
# Compare job tags to runner tags
grep -A2 'tags:' .gitlab-ci.yml
grep -E 'concurrent|limit' /etc/gitlab-runner/config.toml
# Check shared/group runner settings for the project
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/42" | jq '{shared_runners_enabled, group_runners_enabled}'
# Register and (re)start a runner, surviving reboots
sudo gitlab-runner register --url https://gitlab.example.com --token glrt-REALTOKEN
sudo gitlab-runner start
sudo systemctl enable gitlab-runner
Conclusion
A “stuck because the project doesn’t have any runners online” job is GitLab telling you no eligible runner is online for that job. The usual root causes:
- No runner is registered or assigned to the project.
- The runner is paused or offline and not heartbeating to GitLab.
- The job’s
tags:match no runner (or no runner will run untagged jobs). - The runner is registered but the service is not running, or registration failed.
- Shared/group runners are disabled for the project.
- Every eligible runner is busy at its
concurrent/limit, or it is protected-branch-only on an unprotected branch.
Read the exact stuck message first — it tells you whether you have no online runner or a tag mismatch — and the fix is almost always starting the runner service, matching tags, or re-enabling the runners the project depends on.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.