GitHub Actions Matrix include/exclude Produces Wrong Combinations
The matrix expands into unexpected jobs because include and exclude follow specific rules: include can either extend an existing combination or add a brand-new one, and exclude must match every key of a combination to remove it.
What this error means
You get more or fewer matrix jobs than intended - an include entry created a whole new job instead of adding a field, or an exclude removed nothing because its keys did not fully match.
matrix:
os: [ubuntu-latest]
node: [18, 20]
include:
- node: 22 # adds a NEW job (no os), total 3 not 2
exclude:
- node: 18 # only matches if it pins all original keysCommon causes
include extends vs adds depending on keys
If an include entry only sets keys already in the matrix, it expands a matching combination. If it introduces a new value not in the base, it adds a separate job.
exclude must match a full combination
exclude removes a combination only when its keys match an existing generated combination. A partial key set may not match the way you expect.
How to fix it
Be explicit about include entries
Specify all base keys in an include entry when you want to extend a specific combination, not create a new bare one.
matrix:
os: [ubuntu-latest]
node: [18, 20]
include:
- os: ubuntu-latest
node: 20
coverage: true # extends the existing 20 jobVerify the expansion
- Print the matrix context with a debug job to see the real combinations.
- Pin every relevant key in exclude entries so they match exactly.
- Use fail-fast: false while tuning so one leg does not cancel the rest.
How to prevent it
- Treat include as add/extend and exclude as full-match removal.
- Echo the matrix combinations when changing include/exclude.
- Keep the base matrix small and layer specifics via include deliberately.