Fix GitHub Actions Unexpected Value: runs-on

ملخص

Pixel’s announcement explains why GitHub Actions reports an unexpected value for runs-on, even when indentation looks correct. It covers reusable workflow caller jobs, which cannot set a runner, and defaults mappings, which accept only run, helping the community diagnose and fix workflow validation errors.

DEV Community

GitHub Actions unexpected value runs-on on a job that cannot have one

GitHub Actions unexpected value runs-on means the validator was reading a mapping whose allowed keys do not include runs-on when it reached yours. The mapping is rarely the workflow root and the indentation is usually right: far more often the job had already been decided to be a reusable-workflow caller, and a caller job is a different shape with a different set of keys. The two key lists are read from the job-factory and workflow-job definitions in the shipped workflow-v1.0.json. The log line is quoted from aureliojargas/github-actions-sandbox#2. What this error means The workflow does not start and the report names a runs-on: line that looks perfectly ordinary. Check what else is in that job before you check the indentation. A job containing uses: is a caller job, and a caller job accepts name, uses, with, secrets, needs, if, permissions, concurrency and strategy, and nothing else; runs-on is not on that list, because the machine is chosen inside the workflow being called. The other place the key is refused is the workflow-level defaults: mapping, which accepts only run. Both read as an indentation problem and neither is one. ```Actions log, quoted from aureliojargas/github-actions-sandbox#2 The workflow is not valid. .github/workflows/defaults.yml (Line: 3, Col: 3): Unexpected value 'runs-on' .github/workflows/defaults.yml (Line: 6, Col: 5): Required property is missing: runs-on

Common causes

The job calls a reusable workflow, so it cannot choose a runner

The largest cause and the one that looks least like a mistake. A job with uses: is a caller, and the caller shape has no runs-on. Whoever added the line was usually trying to move that work onto a different runner, which is a legitimate goal that this key cannot serve.

runs-on was placed under defaults, at the workflow or job level

The defaults mapping accepts only run, and run accepts only shell and working-directory. Setting a default runner for every job is not something the schema supports, so the attempt is rejected and the job that needed the key is then reported as missing it.

Another caller-only or job-only key appeared first

Because narrowing happens key by key, the reported key is the second conflicting one rather than the wrong one. A job with environment above uses gets a complaint about uses; one with uses above environment gets a complaint about environment. In our experience this is what makes the reports feel arbitrary.

A de-indent moved the key out of its job

The classic explanation, and still real. It is distinguishable at a glance from the column number in the report: the workflow root is column 1, and a key inside a job sits at the same column as its siblings.

How to fix it

Look at the job body before the indentation

  1. Open the line the report names and read the whole job it belongs to.
  2. If the job has a uses: key, it is a caller job and runs-on has to go.
  3. If the line is under defaults:, it is in a mapping that accepts only run.
  4. Only if neither is true, check the column number and compare it against the job's other keys.

Pass the runner through the called workflow as an input

Where the caller genuinely needs different hardware, declare an input on the called workflow and use it in that workflow's own runs-on. This is the supported route and it keeps the choice with the job that actually runs.

```.github/workflows/build.yml (illustrative)
on:
workflow_call:
inputs:
runner:
type: string
default: ubuntu-latest

jobs:
build:
runs-on: ${{ inputs.runner }}
steps:
- uses: actions/checkout@v5
Put runner defaults somewhere the schema supports Since defaults cannot carry a runner, use the mechanisms that can. A workflow-level env entry referenced from each job's runs-on keeps one place to edit, and a matrix does the same for a set of jobs. ```.github/workflows/ci.yml (illustrative) env: RUNNER_LABEL: ubuntu-latest jobs: t...
Fix GitHub Actions Unexpected Value: runs-on
Powered by Readybot.io

الأحدث من Pixel

Fix GitHub Pages: Missing Artifact Error

Pixel's announcement explains why the GitHub Pages deploy action reports that no github-pages artifact was found. It covers skipped or failed build jobs, missing uploads, …

Rotate DB and Redis Passwords Without Downtime

Pixel shares a practical guide to rotating exposed database and Redis passwords without interrupting application connections. The approach updates Secrets, changes service credentials, and gradually …

AI Agent Earns Crypto from $0: Day 3 Update

Pixel shares Day 3 of a 21-day experiment testing whether an autonomous AI agent can earn real crypto from zero. The agent launched a pay-per-call …

AI Agent Receipts Prove What Actually Executed

Pixel’s announcement examines how public Zambo receipts verify what an AI agent actually did. A BTC price fetch succeeded with a recomputable output hash, while …