Skip to content

GitHub Actions Matrix Strategy Error Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about GitHub Actions Matrix Strategy Error Fix. We cover key concepts, practical examples, and best practices.

Your GitHub Actions matrix workflow fails with Error: Unable to evaluate matrix — the matrix JSON syntax is invalid, include/exclude rules conflict, or the matrix produces too many jobs.

The Problem

# WRONG — invalid matrix structure
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: ['18', '20'
        os: [ubuntu-latest, windows-latest]
Error: Unable to evaluate matrix: Invalid JSON

Missing closing bracket on node-version. The matrix configuration must be valid JSON mapped to YAML.

Step-by-Step Fix

1. Fix the matrix syntax

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        node-version: ['18', '20', '22']
        os: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

2. Use include to add dimensions

matrix:
  os: [ubuntu-latest]
  include:
    - os: ubuntu-latest
      node-version: '20'
      experimental: false
    - os: windows-latest
      node-version: '22'
      experimental: true

3. Use exclude to remove combinations

matrix:
  node-version: ['18', '20', '22']
  os: [ubuntu-latest, windows-latest, macos-latest]
  exclude:
    - os: macos-latest
      node-version: '18'
    - os: windows-latest
      node-version: '22'

4. Use dynamic matrix from JSON output

jobs:
  discover:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - id: set-matrix
        run: |
          echo 'matrix={"os":["ubuntu","windows"],"node":["18","20"]}' >> $GITHUB_OUTPUT

  build:
    needs: discover
    runs-on: ${{ matrix.os }}-latest
    strategy:
      matrix: ${{ fromJSON(needs.discover.outputs.matrix) }}
    steps:
      - run: echo "Building on ${{ matrix.os }} with Node ${{ matrix.node }}"

Expected output:

Matrix: 6 combinations (3 node versions x 2 OS)
Job 1/6: ubuntu-latest / 18 ✓
Job 2/6: ubuntu-latest / 20 ✓
Job 3/6: ubuntu-latest / 22 ✓
Job 4/6: windows-latest / 18 ✓
Job 5/6: windows-latest / 20 ✓
Job 6/6: windows-latest / 22 ✓

Prevention Tips

  • Validate matrix YAML with a linter before pushing
  • Use include for sparse matrices instead of full cross-product
  • Cap matrix jobs with max-parallel to avoid resource exhaustion
  • Use continue-on-error: true for experimental combinations
  • Test with a small matrix first, then expand

Common Mistakes with actions matrix

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world GITHUB code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What's the maximum number of matrix jobs?

GitHub Actions limits matrix jobs to 256 per workflow run. Exceeding this causes Error: Matrix size too large. If you need more, split across multiple workflow files or use include to create a sparse matrix instead of the full cross-product.

How do I debug a dynamic matrix that fails?

Print the matrix JSON to the workflow log: echo '${{ steps.set-matrix.outputs.matrix }}'. Verify it's valid JSON with jq .. Check that the job output includes the correct keys and values. Run with act locally to test matrix logic before pushing.

Can I use strategy.matrix.fail-fast with specific job combinations?

Yes. fail-fast: true (default) cancels all in-progress jobs when any job fails. fail-fast: false continues all jobs. You cannot set fail-fast per combination — it applies to the entire matrix. Use continue-on-error: true on specific steps for per-job resilience.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro