Skip to content
Latchkey

GitHub Actions Dynamic Matrix from fromJSON Fails - Not an Array

A dynamic matrix fed by fromJSON of an upstream output fails because the output was empty, not valid JSON, or not shaped as an array the matrix expander accepts.

What this error means

The dependent job fails to expand its matrix, or produces zero jobs, when the JSON it consumes is empty or malformed. The producer job often succeeded, hiding the real cause.

Actions annotation
Error: The template is not valid. .github/workflows/ci.yml:
matrix value 'fromJSON(needs.gen.outputs.list)' did not evaluate to an array

Diagnose it: print the context before you change anything

Most workflow-expression bugs are not syntax errors, they are an expression reading something that is empty. GitHub resolves a missing property to an empty string instead of failing the run, so a wrong reference looks like a logic bug rather than a mistake. Dump the contexts first and you will usually see the answer immediately.

.github/workflows/ci.yml
- name: Dump contexts
  run: |
    echo '--- github ---'   ; echo '${{ toJSON(github) }}'
    echo '--- needs ---'    ; echo '${{ toJSON(needs) }}'
    echo '--- steps ---'    ; echo '${{ toJSON(steps) }}'
    echo '--- matrix ---'   ; echo '${{ toJSON(matrix) }}'
    echo '--- inputs ---'   ; echo '${{ toJSON(inputs) }}'

Check the context is allowed where you used it

Contexts are not available everywhere. The same expression can be valid in a step if and invalid in a job if, which is why an expression that works in one workflow fails when moved.

Where you wrote itContexts available there
run-namegithub, inputs, vars
concurrencygithub, inputs, vars
Top-level envgithub, secrets, inputs, vars
jobs.<id>.ifgithub, needs, vars, inputs
jobs.<id>.steps.ifgithub, needs, strategy, matrix, job, runner, env, vars, steps, inputs
jobs.<id>.outputsFull access, including secrets
Reusable workflow outputsgithub, jobs, vars, inputs

Common causes

Upstream output empty or truncated

If the producer job did not set the output (skipped step, wrong id, or size truncation), fromJSON receives an empty string and cannot produce an array.

JSON not an array of values

A matrix dimension needs a JSON array. A bare object, a quoted string, or trailing-comma JSON makes fromJSON fail or produce a non-array.

How to fix it

Emit valid JSON array as a job output

.github/workflows/ci.yml
jobs:
  gen:
    runs-on: ubuntu-latest
    outputs:
      list: ${{ steps.set.outputs.list }}
    steps:
      - id: set
        run: echo 'list=["18","20","22"]' >> "$GITHUB_OUTPUT"
  test:
    needs: gen
    strategy:
      matrix:
        node: ${{ fromJSON(needs.gen.outputs.list) }}
    runs-on: ubuntu-latest

Validate the JSON before consuming it

  1. Echo the producer output and confirm it is a non-empty JSON array.
  2. Use a tool like jq -c to compact and validate the JSON you emit.
  3. Guard the dependent job so it does not run on an empty list.

Catch it before it reaches CI

Every failure in this cluster is statically detectable. actionlint parses workflow expressions, checks context availability against the same rules above, and validates needs references, so these bugs never need to cost you a run.

Terminal
# one-off
docker run --rm -v "$(pwd):/repo" --workdir /repo rhysd/actionlint:latest -color

# as a job, before anything expensive runs
- uses: actions/checkout@v4
- run: |
    bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
    ./actionlint -color

How to prevent it

  • Always emit compact, valid JSON arrays for dynamic matrices.
  • Map the producer step output to a job output and confirm it is non-empty.
  • Validate the JSON shape (array of scalars or objects) before fromJSON.

Frequently asked questions

What causes GitHub Actions dynamic matrix from fromJSON fails?
There are 2 common causes: upstream output empty or truncated and json not an array of values. If the producer job did not set the output (skipped step, wrong id, or size truncation), fromJSON receives an empty string and cannot produce an array.
How do I fix GitHub Actions dynamic matrix from fromJSON fails?
There are 2 fixes depending on which cause you have: emit valid json array as a job output and validate the json before consuming it. Work through them in order, since the first is the most common.
What does GitHub Actions dynamic matrix from fromJSON fails actually mean?
The dependent job fails to expand its matrix, or produces zero jobs, when the JSON it consumes is empty or malformed.
How do I stop GitHub Actions dynamic matrix from fromJSON fails happening again?
Always emit compact, valid JSON arrays for dynamic matrices. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card