Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for GitLab CI/CD By James Joyner IV · · 9 min read

GitLab CI Error Guide: 'This job is stuck because you don't have any active runners online or available with any of these tags' Tag Mismatch

Fix GitLab's stuck-job tag mismatch: align job tags with runner tags, enable run-untagged, and clear protected/locked runner scope so pending jobs pick up.

  • #gitlab-cicd
  • #troubleshooting
  • #errors
  • #runners

Exact Error Message

The job sits in pending forever, and the job log header shows one of these:

This job is stuck because you don't have any active runners online or available with any of these tags assigned to them: docker, build
This job is stuck because the project doesn't have any runners online assigned to it.
Go to project CI/CD settings

The first variant — the one that lists specific tag names after the colon — is the one this guide covers: you have runners online, but none of them carry every tag the job asked for. That is different from having no runners at all; if you genuinely have zero registered runners, see GitLab CI Error: No runners online.

What the Error Means

GitLab matches a job to a runner with strict set logic: a runner may only pick up a job if the runner’s tag set contains every tag listed in the job’s tags:. If a job requests tags: [docker, build], only a runner tagged with both docker and build (plus optionally more) is eligible. A runner tagged with just docker is not a match.

When no online runner satisfies that subset relationship, the job is not rejected — it stays pending and GitLab surfaces “This job is stuck…”, echoing back the exact tags it could not satisfy. The tags named in the message are the job’s requested tags, so they are your first clue: compare them, character for character, against the tags actually assigned to your runners under Settings > CI/CD > Runners.

The error is purely about eligibility filtering, not capacity. The runner can be idle with free concurrency and still never be offered the job because it fails the tag, untagged, protected, or scope filter.

Common Causes

  • Tag spelling/case mismatch. Job asks for Docker or docker-build; runner is tagged docker. Tags are case-sensitive and must match exactly.
  • Runner has fewer tags than the job requests. Job wants [docker, gpu]; runner only has docker. A runner must be a superset of the job’s tags.
  • “Run untagged jobs” is off and the job has no tags. An untagged job can only run on a runner that has the “Run untagged jobs” checkbox enabled. If every runner is tag-restricted, untagged jobs hang.
  • Protected runner + unprotected branch (or vice versa). A runner marked “Protected” only runs jobs on protected branches/tags. A job on a feature branch will be filtered out even with matching tags.
  • Runner is paused. A paused runner is “online” but offered no jobs.
  • Wrong scope. The runner is a project runner on a different project, or a group runner that was never enabled for this project, so it is online but not assigned here.
  • tags: set in a base job and inherited unexpectedly. An extends: or default: block adds tags the job never intended to request.

How to Reproduce the Error

Register a runner with a single tag, then submit a job demanding two tags:

# Runner registered with only the "docker" tag
gitlab-runner register --non-interactive \
  --url "https://gitlab.com/" --token "$RUNNER_TOKEN" \
  --executor docker --docker-image alpine:3.20 \
  --tag-list "docker" --run-untagged="false"
# .gitlab-ci.yml — asks for a tag the runner does not have
build:
  stage: build
  tags: [docker, build]   # runner only has "docker"
  script:
    - echo "this never starts"

Push it: the pipeline is created and valid, but build stays pending and reports it is stuck on tags docker, build.

Diagnostic Commands

Read the job log header first — it names the exact tags GitLab could not satisfy. Then compare against the runner side:

# List runners this host has registered and their tags
gitlab-runner list

# Verify the runners are still reachable / not removed server-side
gitlab-runner verify

# Inspect the registered tag-list and run-untagged flag in config.toml
sudo cat /etc/gitlab-runner/config.toml | grep -A3 -E '\[\[runners\]\]|tags|run_untagged'

# If the runner won't pick up jobs at all, watch its service logs
sudo journalctl -u gitlab-runner -f

In the UI, the authoritative comparison is Settings > CI/CD > Runners: each runner row lists its tags, its lock/protected status, and whether it accepts untagged jobs. Query the same data via the API:

# Runners assigned to the project, with tags and status
curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/runners" \
  | jq '.[] | {id, description, online, paused, tag_list}'

You can also confirm what tags the job actually requested by viewing the merged config in the Pipeline Editor > View merged YAML, in case extends: or default: injected tags.

Step-by-Step Resolution

  1. Read the tags in the error, e.g. docker, build. These are the job’s requested tags.

  2. Open Settings > CI/CD > Runners and find an online, unpaused runner. Compare its tag list to the requested set, watching for case and hyphen differences.

  3. Align the tags. Either add the missing tag to the runner (edit the runner in the UI or update --tag-list and re-register), or relax the job:

    build:
      tags: [docker]   # only request tags every eligible runner actually has
      script: [make build]
  4. For untagged jobs that hang, enable “Run untagged jobs” on a runner (UI checkbox) or set it in config:

    [[runners]]
      name = "shared-docker"
      run_untagged = true
      [runners.docker]
        image = "alpine:3.20"

    Then restart: sudo gitlab-runner restart.

  5. Fix protected scope. If the runner is “Protected” but the branch is not protected, either unprotect the runner, or protect the branch under Settings > Repository > Protected branches.

  6. Unpause and re-scope. Toggle a paused runner back on, and for a group runner click Enable for this project.

  7. Re-run the pending job (Retry) — no new commit is needed once a matching runner exists.

Prevention and Best Practices

  • Treat tags as a contract. Pick a small, documented tag vocabulary (docker, shell, gpu, arm64) and tag both runners and jobs from it. Inconsistent ad-hoc tags are the number-one cause of stuck jobs.
  • Keep at least one runner with “Run untagged jobs” on so a job that forgets tags: still runs somewhere.
  • Name tags by capability, not host. docker ages better than runner-7, and survives runner replacement.
  • Audit tags in CI. A scheduled job hitting GET /projects/:id/runners can alert when no online runner covers a required tag set.
  • Be deliberate with protected runners for deploy credentials, and make sure the branches that need them are actually protected.
  • For fast triage, the free incident assistant can read a stuck-job message and suggest the missing tag or scope. More patterns live in the GitLab CI/CD guides.

Frequently Asked Questions

Why does my runner show “online” but the job is still stuck? Online means the runner is contacting GitLab, not that it is eligible. Tags, the protected flag, the paused flag, and project scope are all applied after the online check. A perfectly healthy online runner is skipped if its tag set does not contain every tag the job requested.

Do runner tags need to match the job tags exactly, one-to-one? No — the runner must be a superset. A runner tagged [docker, build, linux] can run a job asking only for [docker]. The failure is the reverse: a job asking for more tags than any single runner carries.

My job has no tags: at all — why is it stuck? Untagged jobs only run on runners that have “Run untagged jobs” enabled. If all your runners are tag-restricted, an untagged job has nowhere to go. Enable run_untagged on at least one runner.

Can a protected runner cause this even when tags match? Yes. A protected runner refuses jobs on unprotected branches. The tag message can appear even though the real blocker is the protected flag, so check both when tags look correct.

Where do I see a runner’s exact tags? Settings > CI/CD > Runners in the UI, gitlab-runner list plus config.toml on the host, or GET /api/v4/projects/:id/runners for the assigned set. Compare these against the tags printed in the stuck-job message.

Free download · 368-page PDF

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.