# Blacksmith runner not picked up, and the other errors teams hit

> Blacksmith runner not picked up is usually a label typo or a missing GitHub App. Eight failures on Blacksmith GitHub Actions runners, with the fixes.

Source: https://latchkey.dev/learn/runners/blacksmith-troubleshooting  
Updated: 2026-09-20

Blacksmith runner not picked up is, nine times out of ten, one of two things: a `runs-on` value that does not match a published Blacksmith tag character for character, or the Blacksmith GitHub App missing from the repository that queued the job. Both are configuration rather than product faults, and both have a documented fix.

This page collects the failures teams hit in their first weeks on Blacksmith, with the fix for each and the Blacksmith document that describes it. Most are configuration, several are documented behavior, and the genuine product limits are labeled as such.

Everything was read from docs.blacksmith.sh and blacksmith.sh on 20 September 2026, and where Blacksmith publishes nothing this page says so. For the product overview instead of the error list, [what Blacksmith CI is](/learn/runners/blacksmith-runners-explained) and [Blacksmith pricing explained](/learn/runners/blacksmith-pricing-explained) cover the sizes and the rate card.

## The job stays queued, or quietly runs on a GitHub-hosted runner

The label is exact. Blacksmith tags are `blacksmith-{n}vcpu-{os}-{version}`, with `-arm` for ARM Linux, and the instance-types page lists every valid one. A tag that does not exist matches no runner, and GitHub does not fail that job: it waits out the 24-hour queue timeout, then cancels it.

The usual mismatches: a vCPU count that does not exist for that platform, the wrong Ubuntu suffix, an ARM label on an x64 job, and a `runs-on` nobody changed. Blacksmith publishes the mapping for the three starting points: `ubuntu-latest` to `blacksmith-2vcpu-ubuntu-2404`, `windows-latest` to `blacksmith-2vcpu-windows-2025`, `macos-latest` to `blacksmith-6vcpu-macos-latest`.

Check every job, not the first one. A workflow with one job on Blacksmith and three still on `ubuntu-latest` looks migrated and bills like it was not.

```.github/workflows/ci.yml
jobs:
   build:
-    runs-on: blacksmith-2vcpu-ubuntu-2204-arm64   # invalid: the suffix is -arm
+    runs-on: blacksmith-2vcpu-ubuntu-2204-arm

   test:
-    runs-on: blacksmith-6vcpu-ubuntu-2404        # invalid: no 6 vCPU Linux tier
+    runs-on: blacksmith-8vcpu-ubuntu-2404
```

## Jobs queue in one repository while another repository is served

This one looks impossible, because Blacksmith states it has no concurrency limits. The mechanism is in its own FAQ: runners register through GitHub's organization-level API, so GitHub can hand a live runner any queued job in the organization whose tags match, while Blacksmith provisions capacity only where its app is installed. One repository with the app and two without means the first one's runners are consumed by work Blacksmith never saw.

The documented fix is to install the app everywhere `blacksmith-*` labels appear. Audit it cheaply: search the organization for `runs-on: blacksmith-` and compare the matches against the app's installation page.

Two adjacent failures share a cause. Blacksmith is limited to GitHub organizations, so a personal account cannot use it. And if the organization is missing from the dashboard, the quickstart names three reasons: an unauthenticated SSO session, the app not installed, or a user who is not a member.

## Docker builds are not using the layer cache

Layer caching needs both Blacksmith actions: `useblacksmith/setup-docker-builder@v2` configures a buildx builder with access to previous runs, and `useblacksmith/build-push-action@v2` builds on it. Use the build action alone and the runner falls back to the default builder, which uses no Blacksmith layer cache and reports no analytics.

The newer trap is the `cache-key` input that `setup-docker-builder@v2` requires. Builds sharing a key share a cache, so an unrelated image on the same key evicts your layers and can leave the build slower than no cache at all. A Dockerfile path is the documented default.

One rule catches people whose cache is configured correctly: the runner commits the cache at the end of the job, and only if no other step failed or was canceled, so a flaky test after the build means the build you paid for is not saved.

The oldest Docker rule still applies underneath all of it: a change early in the Dockerfile invalidates every layer after it, so order stable steps first and copy changing source last.

```Both actions, with the cache key scoped to one Dockerfile
- uses: useblacksmith/setup-docker-builder@v2
  with:
    cache-key: services/api/Dockerfile
- uses: useblacksmith/build-push-action@v2
  with:
    push: true
    tags: user/app:latest
```

## A sticky disk fails inside a container job

Sticky disks mount a block device, so a container job needs the container privileged and carrying five Blacksmith environment variables: `VM_ID`, `GITHUB_REPO_NAME`, `BLACKSMITH_STICKYDISK_TOKEN`, `BLACKSMITH_INSTALLATION_MODEL_ID` and `BLACKSMITH_REGION`, plus `sudo`, which slim test images usually lack.

The symptom is specific: without those steps you get a `401`, an `Unauthenticated` error, or permission errors on mount, a signature that does not look like a disk problem. Two limits sit behind the feature: at most 5 sticky disks per job, and a disk purged after 7 days without a mount.

```The container job changes a sticky disk needs
container:
  image: mcr.microsoft.com/playwright:v1.41.1
  options: --privileged
  env:
    VM_ID: ${{ env.VM_ID }}
    BLACKSMITH_STICKYDISK_TOKEN: ${{ env.BLACKSMITH_STICKYDISK_TOKEN }}
```

## A workflow still references useblacksmith cache forks

Those actions are archived. `useblacksmith/cache` and the language-specific forks are unmaintained, and Blacksmith recommends moving to the upstream actions. Nothing replaces them: on a Blacksmith runner the official and popular third-party cache actions are redirected to its colocated cache, with 25 GB free per repository per week against GitHub's 10 GB, evicted after 7 days unused.

Two documented exceptions still talk to GitHub's backend: Rust's `sccache` and the cache option inside `docker/build-push-action`, so if those are your hot paths you are on GitHub's storage rules whatever the rest of the workflow does.

Entries are scoped to their branch or tag by default, matching GitHub's own restriction, and that can be turned off in the dashboard. Latchkey makes the opposite trade: its cache is a one-line swap to `latchkey-dev/cache-action@v1`, carrying the same inputs, with 14-day retention and per-organization isolation ([dependency caching](/documentation/dependency-caching)).

## The first run was slow, and so was the one after a quiet week

A cold first run is expected rather than a fault. The compute is not the slow part, since the docs put microVM boot at under 3 seconds; what is cold is the cache, because the first Docker run after the switch is uncached and later runs mount the hydrated layer cache.

The one to watch is the second cold run, weeks later. The sticky disk is evicted after 7 days idle and BuildKit drops layers unused for 8 days, so a weekly pipeline pays the uncached price most times it runs, and a scheduled warm-up build inside that window is cheaper than the rebuild.

## The free minutes ran out much sooner than expected

The 3,000 free minutes a month are per organization and denominated in x64 2-vCPU minutes, so bigger runners draw them down proportionally at the conversions the instance-types FAQ publishes.

| Runner | Draw per minute | What the 3,000 free minutes buy |
| --- | --- | --- |
| Ubuntu x64, 2 vCPU | 1 | 3,000 minutes |
| Ubuntu x64, 4 vCPU | 2 | 1,500 minutes |
| Ubuntu x64, 8 vCPU | 4 | 750 minutes |
| Ubuntu x64, 32 vCPU | 16 | 187 minutes |
| Ubuntu ARM, 2 vCPU | 0.625 | 4,800 minutes |
| Windows x64, 2 vCPU | 2 | 1,500 minutes |
| macOS M4, 6 vCPU | 20 | 150 minutes |

## The image is nearly GitHub's image, except where it is not

Ubuntu x64 and ARM runners carry the same dependencies as GitHub's official runner images, which is why most migrations are uneventful. Windows is the documented exception: it is based on GitHub's Windows Server 2025 image but excludes the full Visual Studio IDE in favor of VS Build Tools 2022, plus Visual Studio extensions, EdgeDriver, WinAppDriver and the Azure Cosmos DB Emulator. A job that expects any of those fails on a runner that is otherwise a drop-in.

Two platform limits are documented rather than incidental. Docker Linux containers are unsupported on Windows runners because of nested virtualization constraints, though Windows containers matching the host work through process isolation. Nested virtualization is x64 Linux only, so KVM jobs and Android emulator tests will not run on ARM.

One surprise runs the other way: when the fleet has spare capacity, Blacksmith bumps a runner to the next tier at no extra cost, so a job that asked for 4 vCPU sometimes gets 8.

## When the failure is not a Blacksmith problem at all

Some failures are not about the runner vendor at all: a registry timeout, an out-of-memory kill, a disk that filled mid-job, a browser binary that did not install. On Blacksmith, as on GitHub-hosted runners, those fail the job, bill the minutes, and bill again on the re-run.

Latchkey differs on that one axis, retrying transient failures inside the same job ([self-healing](/documentation/self-healing)), while Blacksmith sells arm64, Windows, macOS and 3,000 free minutes that Latchkey does not.

## FAQ

### My Blacksmith job stays queued or runs on a GitHub-hosted runner. Why?

Either the `runs-on` value does not match a published Blacksmith tag exactly, or the GitHub App is not installed on that repository. Check the tag character for character, then the app installation. GitHub does not fail a job whose label matches nothing; it waits out the 24-hour queue timeout first.

### Why was my first Blacksmith run slow?

Caches start cold, not the machine: the docs put microVM boot at under 3 seconds, but the first Docker build after switching is uncached and later runs mount the hydrated cache. If runs are a week or more apart, the 7-day sticky disk eviction and 8-day BuildKit collection mean you keep paying the cold price.

### Do I need both Blacksmith Docker actions to get layer caching?

Yes. Without `useblacksmith/setup-docker-builder` the runner falls back to the default builder, which uses no Blacksmith layer cache and reports no analytics. The setup action also requires a `cache-key` that decides which builds share a cache; the documented default is the Dockerfile path.

### How fast do Blacksmith free minutes run out on a larger runner?

Proportionally to size, because they are x64 2-vCPU minutes: a 4 vCPU runner draws two a minute and an 8 vCPU runner four, which is 1,500 and 750 wall-clock minutes. ARM draws 0.625, Windows double, and a 6 vCPU macOS runner 20, or 150 minutes.

## References

- [Blacksmith instance types, runner tags, free minutes and the queuing FAQ](https://docs.blacksmith.sh/blacksmith-runners/overview)
- [Blacksmith dependency caching, archived cache forks and the documented exceptions](https://docs.blacksmith.sh/blacksmith-caching/dependencies-actions)
- [Blacksmith sticky disks: container requirements, limits and eviction](https://docs.blacksmith.sh/blacksmith-caching/dependencies-sticky-disks)
- [Blacksmith Docker builds: both actions, the cache key and the commit rule](https://docs.blacksmith.sh/blacksmith-caching/docker-builds)
- [Blacksmith quickstart: the GitHub App, the label mapping and dashboard access](https://docs.blacksmith.sh/introduction/quickstart)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
