Blacksmith runner not picked up, and the other errors teams hit
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 and 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.
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-2404Jobs 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.
- uses: useblacksmith/setup-docker-builder@v2
with:
cache-key: services/api/Dockerfile
- uses: useblacksmith/build-push-action@v2
with:
push: true
tags: user/app:latestA 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.
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).
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), while Blacksmith sells arm64, Windows, macOS and 3,000 free minutes that Latchkey does not.
Key takeaways
- A queued job is a label that matches no runner, and GitHub waits 24 hours before canceling it rather than failing fast.
- Install the GitHub App on every repository using
blacksmith-*labels: runner registration is organization-wide, so one missing install starves the others. - Docker caching needs both actions plus a
cache-key, and the cache is only committed if no other step in the job failed. - Sticky disks inside a container need privileged mode, five environment variables and
sudo, or you get a 401. - The 3,000 free minutes are 2-vCPU minutes: 750 on an 8 vCPU runner, 150 on macOS.
Frequently asked questions
My Blacksmith job stays queued or runs on a GitHub-hosted runner. Why?
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?
Do I need both Blacksmith Docker actions to get layer caching?
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?
Related guides
References
- Blacksmith instance types, runner tags, free minutes and the queuing FAQ
- Blacksmith dependency caching, archived cache forks and the documented exceptions
- Blacksmith sticky disks: container requirements, limits and eviction
- Blacksmith Docker builds: both actions, the cache key and the commit rule
- Blacksmith quickstart: the GitHub App, the label mapping and dashboard access
- GitHub Actions documentation