Each standard job must specify runs-on to choose a runner. Omitting it (or misindenting it so it is not seen as a job key) makes the workflow invalid. Jobs that only call a reusable workflow via uses are the exception.
What this error means
The workflow is rejected reporting runs-on is required for a job, after the key was missing or misplaced.
github-actions
Invalid workflow file: .github/workflows/ci.yml#L5
'runs-on' is required and must be a string or an array.
Common causes
runs-on missing on a standard job
A job that runs steps must declare a runner via runs-on.
runs-on misindented
Wrong indentation places runs-on outside the job, so it is not recognized.
How to fix it
Declare a runner on every standard job
Add runs-on with a label like ubuntu-latest at job scope.
For reusable-workflow caller jobs, use uses instead of steps/runs-on.
Verify indentation so runs-on is a direct job key.
.github/workflows/ci.yml
jobs:build:runs-on:ubuntu-lateststeps:- run:echo ok
How to prevent it
Lint workflows so missing runs-on is caught before push.
Remember reusable-workflow caller jobs use uses, not runs-on.
Frequently asked questions
What causes ""runs-on is required""?
A job that runs steps must declare a runner via runs-on.