GitLab CI Job Stuck — No Runner Matches the Tags
Fix jobs stuck at "This job is stuck" by aligning runner tags, checking shared-runner availability, and removing unmatched tag requirements.
Symptoms
- A pipeline job shows "This job is stuck because you don't have any active runners"
- Jobs with a specific tag never start while untagged jobs do
- Stuck jobs spend the whole timeout pending
Possible causes
- The job tags do not match the tags on any registered runner
- All matching runners are offline, paused, or at capacity
- Shared runners are disabled for the project
Diagnosis steps
Compare job tags with runner tags
grep -n "tags:" .gitlab-ci.yml; gitlab-runner listInterpretation
If no runner declares the job tag, the job can never be picked up.
Check runner availability in GitLab
Admin → Runners → filter by tag and statusInterpretation
Offline or paused runners explain a stuck job even when tags match.
Root cause
GitLab schedules a job only on a runner that advertises every tag the job requires. A tag with no matching runner leaves the job pending until timeout ("stuck"), because no runner is eligible.
Fix
Align tags between jobs and runners, register a runner with the needed tags, ensure matching runners are online and unpaused, and remove unnecessary tags from jobs.
Risk note
Using tags that only exist on ephemeral runners makes pipelines flaky when they scale down; document runner fleet requirements.
Verify the fix
Rerun the pipeline and confirm the job is picked up by a matching runner and completes; verify the runner shows the job in its recent builds.
Symptoms
This debugging guide addresses “GitLab CI Job Stuck — No Runner Matches the Tags”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.
Observed symptoms include:
- A pipeline job shows “This job is stuck because you don’t have any active runners”
- Jobs with a specific tag never start while untagged jobs do
- Stuck jobs spend the whole timeout pending
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Compare job tags with runner tags
grep -n "tags:" .gitlab-ci.yml; gitlab-runner list
If no runner declares the job tag, the job can never be picked up.
Step 2: Check runner availability in GitLab
Admin → Runners → filter by tag and status
Offline or paused runners explain a stuck job even when tags match.
Likely contributors, in order of frequency:
- The job tags do not match the tags on any registered runner
- All matching runners are offline, paused, or at capacity
- Shared runners are disabled for the project
Root Cause
GitLab schedules a job only on a runner that advertises every tag the job requires. A tag with no matching runner leaves the job pending until timeout (“stuck”), because no runner is eligible.
The Fix
Align tags between jobs and runners, register a runner with the needed tags, ensure matching runners are online and unpaused, and remove unnecessary tags from jobs.
Watch out: Using tags that only exist on ephemeral runners makes pipelines flaky when they scale down; document runner fleet requirements.
stages: [build]
build:
stage: build
tags:
- docker # every eligible runner must advertise this tag
- linux
script:
- make build
# check registered runners and their tags
# gitlab-runner list
# gitlab-runner verify
Verify and Prevent
Rerun the pipeline and confirm the job is picked up by a matching runner and completes; verify the runner shows the job in its recent builds.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.