Skip to content
Latchkey

GitHub Actions Label-Based Routing Sends Jobs to the Wrong Runner

A job lands on the wrong runner pool because multiple fleets share a label. With overlapping labels, GitHub may dispatch to any matching runner, so a job meant for GPU or arm64 runs somewhere else.

What this error means

A job runs on an unexpected runner - wrong architecture, missing tools, or a pool you meant to reserve - because more than one runner set matched the requested labels.

.github/workflows/ci.yml
# both an x64 and an arm64 fleet are labeled [self-hosted, build]
runs-on: [self-hosted, build]   # may match either fleet

Common causes

Labels overlap across fleets

When two runner groups share the same labels, any of them can claim a matching job, so routing is not deterministic.

Too-generic label set

Requesting only broad labels (self-hosted, linux) without a distinguishing one lets unintended runners pick up the job.

How to fix it

Add a distinguishing label

Give each fleet a unique label and request it so only the intended pool matches.

.github/workflows/ci.yml
# arm64 fleet carries 'arm64'; x64 fleet carries 'x64'
runs-on: [self-hosted, build, arm64]

Use runner groups for isolation

  1. Assign unique, specific labels per fleet and request the exact set.
  2. Use runner groups to restrict which repos and jobs reach a fleet.
  3. Avoid relying on broad shared labels for routing-sensitive jobs.

How to prevent it

  • Give every runner fleet a unique distinguishing label.
  • Request specific labels for routing-sensitive jobs.
  • Isolate sensitive fleets behind runner groups.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →