Read · intermediate
Node 20 left GitHub Actions: check the actions, not just your app
GitHub's Node 20 runner retirement calls for two different checks: the JavaScript actions your workflows use and the Node version your project tests.
Your workflow might say node-version: 20 and still run its actions on Node 24.
Or it might never mention Node at all and depend on an old JavaScript action.
Those are different problems, and this week’s GitHub Actions change makes the
difference worth checking.
On September 23, GitHub announced that Node 20 is no longer available to
JavaScript actions on its runners.
The temporary ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION escape hatch is gone.
GitHub tells action authors to publish a node24 version, action users to
update their references, and self-hosted runner operators to check platform
support. This applies to github.com and GitHub with Data Residency; do not
assume the same rollout for a separate GitHub Enterprise Server installation.
Two Node versions in one workflow
A JavaScript action declares its own runtime in action.yml or action.yaml:
runs:
using: node24
main: dist/index.js
GitHub’s action metadata reference
says runs.using selects the runtime for that action’s code. By contrast,
actions/setup-node puts a chosen Node version on the job’s PATH for your
build and test commands, as the Node workflow guide
explains. Changing node-version in a workflow does not change the runtime
declared by a third-party action. Updating an action does not automatically
change the Node version your application tests against.
That separation gives you a short audit with two owners:
- Workflow owner: list each
uses:reference in.github/workflows/. Check the referenced release or pinned commit for a Node 24-compatible action. Update stale references to a verified release. For local actions, inspect theiraction.ymloraction.yamltoo. A workflow text search alone cannot tell you what runtime a remote tag or commit declares. - Action author: change
runs.usingtonode24, rebuild any committed distribution file, run the action’s tests on supported runners, and publish a new release. Then tell users which tag or commit contains the update. - Application maintainer: keep the
setup-nodematrix that matches the Node versions your application actually supports. Treat a change to that matrix as a separate compatibility decision.
Here is the starting inventory, not the whole audit:
rg -n 'uses:|node-version:|ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION' .github/workflows
rg -n 'using: node(20|24)' --glob 'action.y*ml' .
The second command checks local action metadata. It cannot inspect remote actions, so open the source for each pinned revision. If you pin a full commit SHA, move to a verified new SHA rather than assuming a newer tag changes the pinned code. GitHub’s action security guidance explains why full SHAs give an immutable reference and why tags can move.
Self-hosted runners need one more check
GitHub’s retirement notice says Node 24 is incompatible with macOS 13.4 and earlier and has no official ARM32 support. If your jobs use self-hosted runners on either platform, update the host or move those jobs to a supported runner before treating an action version bump as the fix. Test on the actual runner label; a green GitHub-hosted run does not verify your own machine.
The takeaway
Audit the action runtime and the application runtime separately. Start with
uses: references, inspect the releases they resolve to, then run one real
workflow on every runner class you depend on. That turns a broad deprecation
notice into a small, reviewable migration list.
Sources
- GitHub Changelog, Node 20 is no longer available in GitHub Actions, September 23, 2026.
- GitHub Docs, Metadata syntax reference.
- GitHub Docs, Building and testing Node.js.
- GitHub Docs, Secure use reference.