Lesstep
GitHub Actions · Checked November 3, 2026

GitHub Actions: "The template is not valid"

The run started, and the runner then evaluated an expression whose result it could not use. The file itself passed validation, which is why it reads as correct. The line and column point at the expression, in the workflow or in an action's action.yml. Where it stops tells you which part: at Set up job, in two or three seconds, it is the job's own keys (services:, container: and the like); at a step, it is that step's env:, with:, if: or continue-on-error:.

What it looks like

The template is not valid. .github/workflows/release.yml (Line: 172, Col: 27): Error reading JToken from JsonReader. Path '', line 0, position 0.
The template is not valid. .github/workflows/build.yml (Line: 185, Col: 21): Unexpected value ''
The template is not valid. System.TimeoutException: hashFiles('code-index.db.gz') couldn't finish within 120 seconds.

1. "Error reading JToken from JsonReader": fromJSON on an empty string

fromJSON('') fails, so an output that was never set breaks the expression. The usual case now is release-please: its pr output is empty on a run that opens or updates no release pull request, so fromJSON(steps.release.outputs.pr).headBranchName fails after each release merge (compose-preview-mcp #151), and in pulumi-provider-git on 6 of 10 runs (#54).

An if: on the same step does not protect it. The runner evaluates a step's env: before its if:, and fails the step when that evaluation fails (StepsRunner.cs). It does this for later steps even after an earlier step failed, so in envoyproxy/examples this error was printed on top of the real one (#1526). Pass the raw text and parse it in the shell, which several of these projects did:

- if: steps.release.outputs.pr != ''
  env:
    RELEASE_PR: ${{ steps.release.outputs.pr }}
  run: |
    branch=$(jq -r .headBranchName <<< "$RELEASE_PR")
    echo "branch=$branch" >> "$GITHUB_OUTPUT"

Or give fromJSON something to read: fromJSON(steps.release.outputs.pr || '{}'). That covers an empty value only. Text that is not JSON, such as a free-text workflow_dispatch input, still fails (gh-aw #64249).

2. "Unexpected value ''": an empty value where one is required

3. hashFiles: "couldn't finish within 120 seconds"

hashFiles() has a fixed 120-second limit (HashFilesFunction.cs), and a ** pattern walks the whole workspace, including node_modules and anything the job cloned or built. In code-search-index the if: of one step timed out, and the publish step after it was skipped too (#52). Name the file without ** when you know where it is (hashFiles('package-lock.json')). To test whether a file exists, a step that writes an output does not walk the workspace at all; code-search-index replaced its hashFiles conditions with one:

- id: files
  if: always()
  run: |
    if [ -f code-index.db ]; then echo "db=true"; else echo "db=false"; fi >> "$GITHUB_OUTPUT"
- if: steps.files.outputs.db == 'true'
  run: ./publish.sh

4. hashFiles: "An error occurred trying to start process '…/externals/node20/bin/node'"

hashFiles() runs on the runner's own copy of Node.js. Up to runner 2.337 that was node20, so a runner installed without it fails at every hashFiles(), usually in an actions/cache key: a minimal image on RunsOn (runner-images-for-aws #78) and a runner packaged in Nix (consortium-autoresearch #49). The 2.338.0 release notes: "The runner's own Node usage (hashFiles(), ./run.sh --check, and the service wrapper runsvc.sh) now uses Node 24 instead of Node 20". Updating the runner to 2.338.0 or later fixes it.

Telling it apart

See failed jobs from IntelliJ IDEA

Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).

GitHub and GitHub Actions are trademarks of GitHub, Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc. or JetBrains.

More: "Invalid workflow file" · "Unable to process file command" · Docker Hub's pull limit · GitHub Actions plugins for IntelliJ IDEA compared · 日本語