GitHub Actions conditional matrix entry not skipping in CI
A job-level if: cannot remove one matrix leg based on that leg's values in the way people expect, because the job condition applies to the job, not per-combination in the matrix definition. To drop combinations, use exclude or build the matrix dynamically.
What this error means
A matrix leg you tried to skip with an if still appears (or all legs skip together), because the condition does not selectively remove a single combination from the expansion.
jobs:
test:
if: matrix.os != 'windows-latest' # not evaluated as a per-leg matrix filter
strategy:
matrix:
os: [ubuntu-latest, windows-latest]Common causes
Job if is not a per-leg matrix filter
The if at job level gates the whole job. It is not the mechanism for removing individual combinations from a static matrix.
Trying to filter combinations declaratively with if
People reach for if to prune a combination, but the matrix expansion happens before the job condition applies per leg.
How to fix it
Use exclude to drop the combination
- Move the condition into an
excludeentry with the exact keys. - The excluded combination is never created.
- Verify the expanded matrix no longer contains it.
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
exclude:
- os: windows-latest
node: 18Build the matrix dynamically for complex rules
For conditions that cannot be expressed with exclude, generate the matrix JSON in a setup job and consume it with fromJSON.
matrix=$(jq -c 'map(select(.os != "windows-latest"))' base.json)
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"How to prevent it
- Prune combinations with exclude, not a job-level if.
- Use a dynamic matrix for rules exclude cannot express.
- Skip individual steps with if, but drop legs with exclude.