SIGNAL / TOOLS

Node 20 Removed from GitHub Actions: How to Migrate to Node 24

SOURCEGitHub
PUBLISHEDSeptember 23, 2026
LAYERTools
SIGNAL SCORE28/100

SXF / VERIFIED DEVELOPER CHANGELOG · UPDATED NOVEMBER 8, 2026

On September 23, 2026, GitHub ended Node 20 support as a JavaScript-action runtime and switched Actions execution to Node 24. The temporary ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION opt-out no longer works. Maintainers should release JavaScript actions with runs.using: node24; workflow owners should upgrade incompatible action versions. This is not the same as removing every ability to run Node 20 application code in a job.

IMPORTANT NOVEMBER CLARIFICATION

GitHub's runner team clarified on November 4 that node20 action metadata was being executed using Node 24 and that some runner packages still contained the old binary for compatibility. This is a temporary packaging detail, not supported runtime availability or a reason to keep old actions untested.

SXF TECHNICAL VIEW

The highest-risk migrations are self-hosted or old third-party actions with nonportable dependencies. Audit both the action runtime and the project runtime separately, upgrade supported dependencies, verify the runner and use repeatable acceptance tests before release.

SXF / ORIGINAL GITHUB ACTIONS MIGRATION GUIDE

Node 20 is no longer available in GitHub Actions: what to fix and what not to confuse.

Reviewed November 8, 2026

GitHub Actions retired Node 20 as a supported JavaScript-action runtime on September 23, 2026. Runners now execute JavaScript actions with Node 24, and the temporary override ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true has expired. If you're searching for “Node 20 is no longer available in GitHub Actions,” “GitHub Actions Node 24 migration” or “runs.using node24,” the first task is to determine whether your problem is in a JavaScript action, a workflow's Node application runtime, or a self-hosted runner. They're related but not identical. This guide explains the change, gives tested-by-source migration patterns, and proposes SXF's own acceptance checklist for avoiding avoidable CI outages. Read GitHub's official retirement notice.

FINAL CUTOFFSeptember 23, 2026Supported Node 20 action runtime retired
JAVASCRIPT ACTIONSNode 24GitHub Actions execution runtime
OLD OPT-OUTRemovedCannot force supported Node 20 behavior
SELF-HOSTED RUNNERSUpdate requiredVerify versions, OS and CPU architecture

What does “Node 20 is no longer available in GitHub Actions” actually mean?

GitHub's September 23, 2026 changelog states that JavaScript actions now use Node 24 on GitHub Actions runners, and that a temporary opt-out is no longer available. The change applies to github.com and GitHub with Data Residency. If you maintain an action, GitHub recommends changing its metadata runtime from node20 to node24 and publishing a new release. If you consume actions, upgrade to a current release that supports Node 24.

A JavaScript action is a packaged unit such as a checkout, setup or custom repository action. Its action.yml or action.yaml specifies the runtime under runs.using. The runner executes that JavaScript, including any configured pre- and post-job scripts. That is not the same setting as the Node version installed for your repository's npm test or node app.js command.

Was the Node 20 binary physically removed from every runner?

Do not infer that from the announcement's headline. In a November 4, 2026 GitHub runner-team clarification, an engineer said all Actions, including those whose metadata still declared node20, were being run under Node 24. The team had kept a Node 20 binary in runner packages temporarily for compatibility, with removal planned later in November. That packaging detail does not reinstate the supported Node 20 runtime or guarantee an old JavaScript action works unchanged.

It also explains a common source of confusion: an action can still contain runs.using: node20 in its metadata while being executed with Node 24. The actionable question is whether its code and dependencies are Node-24 compatible, not whether the string node20 happens to appear in a repository.

GitHub Actions Node 20 deprecation timeline: 2025–2026

GitHub first described the deprecation on September 19, 2025 and subsequently revised its migration schedule. The official note lists June 16, 2026 as the start of Node 24 by default and September 23 as the cutoff for the temporary Node 20 override. The original article's notices include the date revisions; later comments should not be confused with a new grace period. Official timeline with editor's notes.

DateMilestonePractical impact
September 19, 2025GitHub announced Node 20 deprecationAction maintainers were told to prepare for Node 24
March 24, 2026Node.js 20 last maintained release / EOLUpstream security fixes no longer supplied for the release line
June 16, 2026GitHub switched the default JS action runtime to Node 24Temporary legacy-runtime override was still permitted
September 23, 2026Node 20 action runtime retiredTemporary opt-out ended; Node 24 is required
November 4, 2026Runner-team clarified physical binary retentionSome packages still included Node 20; actions nonetheless ran on Node 24

Separately, the Node.js release schedule reports Node 20 (Iron) reaching end of life after its March 24, 2026 update. Upstream EOL is a security-and-maintenance event; GitHub's September retirement is a specific CI infrastructure policy. They have related motivations but different operational effects.

Does actions/setup-node with node-version: 20 stop working?

Not automatically because of this particular GitHub announcement. The node-version input to actions/setup-node requests a Node executable for the steps in your job. The runs.using setting in the setup action's own metadata determines which Node executable runs the setup action. A Node-24-compatible setup action can, in principle, install another Node release for application scripts, subject to version availability and other constraints. Official actions/setup-node reference.

Where you see Node 20What it controlsRecommended response
runs.using: node20 in action.ymlBuilt-in runtime for an individual JavaScript ActionRebuild, retest and release for node24
node-version: '20' in setup-nodeNode executable used by subsequent shell/run stepsPlan application migration to a supported LTS; test dependencies
node:20 in DockerfileNode image inside your containerUpgrade and test container and dependencies independently
Self-hosted runner's bundled runtimeRunner software that executes JavaScript actionsUpdate runner; verify Node 24, OS and architecture compatibility
Third-party action pinned to an old tagRemote action's own code and metadataFind current Node-24-compatible version and test it

Security caution: Keeping a Node 20 job for a compatibility test is not a recommendation to run EOL Node 20 in production. The Node.js EOL guidance explains that unmaintained lines no longer receive normal security fixes. Distinguish an unavoidable short-lived migration test from a maintained production build.

How to migrate a custom JavaScript GitHub Action from Node 20 to Node 24

If your repository publishes an action, inspect action.yml or action.yaml at its root or within .github/actions/. GitHub's action metadata syntax specifies the runs.using value. A minimal new configuration can be:

action.yml — JavaScript action runtime
name: "My JavaScript action"
description: "Run a checked JavaScript task"
runs:
  using: "node24"
  main: "dist/index.js"

The change is necessary but may not be sufficient. Modernize libraries that depend on older Node internals; confirm whether the action's bundled dist/index.js uses modern ESM or CJS behavior correctly; rebuild committed distribution output; and exercise any declared pre and post hooks. GitHub does not rebuild your committed action bundle just because you edit its metadata.

  1. Find the action declaration. Check root action.yml / action.yaml and custom action directories. Identify Node 20 references in action metadata, not only workflow commands.
  2. Change the runtime. Set runs.using to node24; verify documented main, pre and post file paths.
  3. Update and rebuild. Install supported dependencies and regenerate any checked-in dist/ bundle using the project's build pipeline.
  4. Run a local and CI test. Execute action unit tests and smoke-test the packaged action on a compatible runner; check initialization and post-job cleanup.
  5. Publish a version. Tag and release the updated action, record any breaking changes and update workflows that consume the action.
  6. Observe real runs. Check logs, outputs, network behavior, artifact uploads and expected permissions in the target environment.

Before/after: a safe metadata-only example

Before
runs:
  using: "node20"
  main: "dist/index.js"
After
runs:
  using: "node24"
  main: "dist/index.js"

This is an illustrative syntax change, not a guarantee of binary compatibility. Some old packages, native modules or bundled code require additional changes. The actual test should exercise the same inputs and outputs as production usage.

How to update workflows that consume Node 20-era actions

If your repository uses JavaScript actions, inspect files in .github/workflows/, especially lines beginning uses:. The referenced action may live in another repository, so looking only for node20 inside your own YAML cannot fully audit dependencies. Read each vendor's release notes and action metadata for the pinned version.

Example workflow with Node-24-compatible first-party actions
name: Node 24 smoke test
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: "24"
          cache: "npm"
      - run: npm ci
      - run: npm test
      - run: npm run build --if-present

Important: These v5 references are illustrative known Node-24-compatible releases, not a claim that v5 remains the latest major in November 2026. Both actions/checkout and actions/setup-node document the move to Node 24 in v5, and their repositories document newer majors with additional changes. Select a current, reviewed version suitable for your runner; for sensitive workflows use verified immutable references or GitHub workflow dependency lockfiles where applicable.

This example deliberately uses node-version: "24" because the sample project is also being tested on a supported Node release. If your application still requires 20 temporarily, that is a separate application migration decision from the underlying action's own runtime. Testing applications on Node 24 and testing JavaScript actions under Node 24 should both be part of a complete migration.

How to audit action references quickly

Basic repository searches (not a full dependency audit)
# List referenced actions in workflow YAML
grep -RIn "uses:" .github/workflows/

# Find local JavaScript action runtime declarations
grep -RIn "using:.*node20" .github/actions/ 2>/dev/null || true

# Inspect the job runtime explicitly
node --version
npm --version

The second command only scans local actions under the standard folder. A third-party uses: vendor/action@tag dependency stores its action.yml in the vendor's repository, and a pinned SHA may refer to an older build. GitHub's secure-use reference explains dependency review, immutable pinning and supply-chain controls. Do not automatically update every major version without checking breaking changes.

Node 24 requirements for self-hosted GitHub Actions runners

The migration is especially consequential for self-hosted runners. GitHub's Node-24 migration notice says Node 24 is incompatible with macOS 13.4 and earlier and is not officially supported on ARM32. The September retirement applies to GitHub-hosted and supported self-hosted execution environments, but your team controls the software and OS image on self-hosted machines. GitHub's retirement announcement.

GitHub's official checkout and setup-node READMEs specify Actions Runner v2.327.1 or later for the Node-24-based v5 releases. Newer action features can require still newer runners; for example checkout v6 calls out an additional runner requirement when performing authenticated Git commands from a Docker container action. Do not stop at the minimum version for an earlier major if you choose a newer release.

Self-hosted checkWhat to verifyCommon resolution
Runner applicationCurrent supported version; at least compatible with the actions you useUpdate runner software/image and retest
macOS hostNot macOS 13.4 or earlier for Node 24Move to a supported macOS host
CPU architectureNode 24 support; ARM32 is no longer supported in this transitionMove to a supported architecture
Docker and packagesAction dependencies, Linux container support and image compatibilityRebuild containers and retest their hooks
Runner updatesAuto-update or manually managed image and service versionFollow documented runner upgrade cadence

GitHub's self-hosted runner documentation explains that hosts need ongoing runner updates to process new Actions features; older runner versions may stop receiving work. Do not treat fixing a JavaScript action as sufficient if the host operating system itself cannot run the required version.

Troubleshooting common GitHub Actions Node 20 / Node 24 errors

SymptomLikely cause to investigateNext check
A previously working action fails after SeptemberOld action code or native dependency incompatible with Node 24Read action changelog; update and test with the same inputs
Legacy opt-out has no effectACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION expiredRemove override and migrate action code/runtime
Self-hosted job fails before action startsRunner binary too old or unsupported OS/CPU architectureCheck runner version, platform and required action version
Action metadata still says node20Old published action tag or unreleased metadataChoose compatible release and validate actual Node 24 behavior
Job still prints node -v as v20Job runtime selected via setup-node or another PATH changeInspect setup-node configuration; this is not the action runtime
Build fails on upgraded Node 24 projectApplication dependency, native package or module compatibilityRun clean install and test project under supported Node version

Why the opt-out is not a rollback plan

Before September 23, GitHub offered ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true as a temporary migration escape hatch. GitHub now explicitly says this path is no longer available. Leaving the variable in a workflow can make troubleshooting harder because it implies a fallback that is no longer supported. The correct resolution is to maintain Node-24-compatible actions and supporting runners.

What about a warning that references Node 20?

A warning or outdated metadata does not by itself prove the actual running interpreter is Node 20. Inspect the action's version, runner logs and official compatibility notes. GitHub's November 4 clarification reports that actions declaring Node 20 were still being executed with Node 24. If a failure persists, reproduce it in a minimal workflow and isolate whether it occurs during setup, main execution, post-job cleanup or an application step. Runner-team clarification.

SXF analysis: this is a supply-chain migration, not just a version bump

Our editorial assessment: the biggest risk in the Node 20 retirement is not the text replacement node20 → node24. It is the chain of dependencies behind a CI job. Workflows load actions from different repositories, often pinned to majors or commits. A GitHub-hosted runner can move to Node 24 without every third-party action maintainer having tested the change. At the same time, older self-hosted runner images can make a supported action unusable. Successful migration requires evidence at the workflow, action, runner and application levels.

That gives security teams a second opportunity: audit the trust and permissions of every action while updating it. Check whether the action has access to repository write permissions or production secrets, whether a release tag can be changed, and whether a forked pull request can influence a privileged workflow. GitHub's secure-use guidance recommends dependency lockfiles for verified and transitive action sources, or full-length SHA pinning where lockfiles are not in use. This is an independent concern from Node compatibility, but migration work is an efficient moment to address both.

Original SXF seven-gate migration acceptance framework

GateReview questionSuggested evidence
1 · InventoryHave all first- and third-party JavaScript actions been listed?Workflow references and dependency graph
2 · RuntimeDoes each custom/published action support Node 24?Metadata, packaged bundle and version release note
3 · Host supportCan every required runner execute the chosen action?Version, OS and architecture inventory
4 · Functional testDo setup, main, post and actual job commands work?Clean CI run, tests, generated artifacts
5 · SecurityAre permissions, action supply chain and secrets bounded?Token scopes, action locks/pins and review
6 · Rollback readinessCould a bad deployment be contained without relying on old Node 20?Known-good Node-24-compatible release and change plan
7 · OwnershipWho watches failures and reviews updates over time?Maintainer, alerting and update policy

This seven-gate SXF framework is original editorial guidance for evaluating a CI migration, not a prescribed GitHub compliance standard or a claim that SXF executed these tests on your repository. It measures practical readiness rather than counting updated YAML strings. A migration that passes all seven gates should have a defensible evidence trail; it still cannot guarantee that every future dependency change will be safe.

A migration decision tree for three kinds of maintainers

IF YOU MAINTAIN AN ACTION

Release a Node-24-compatible package

Change metadata, upgrade dependencies, rebuild the distribution, exercise hooks and publish a tested version.

IF YOU OWN A WORKFLOW

Review upstream action versions

Check referenced actions, upgrade supported releases and validate actual behavior, then protect the dependency chain.

IF YOU OPERATE SELF-HOSTED RUNNERS

Fix the environment first

Upgrade the runner and unsupported operating systems or CPU architecture before troubleshooting individual action code.

Related SXF context: Actions Runner Controller updates, GitHub least-privilege management, AI Agent Security, and Agent Reliability. The last two cover broader automation risk; they are not direct confirmation of this Node runtime change.

Frequently asked questions: Node 20 removal from GitHub Actions

When did GitHub Actions stop supporting Node 20 for JavaScript actions?

September 23, 2026. GitHub's final retirement notice says JavaScript actions now run on Node 24 and the temporary opt-out is unavailable.

Does a workflow using node-version: 20 automatically fail?

No. That setup-node input selects a job's application runtime, distinct from the runtime used to run the JavaScript action itself. Node 20 remains end-of-life and should be migrated for security.

What is the action.yml migration?

For a custom JavaScript action, change runs.using to node24, rebuild any bundled JavaScript, test setup/main/post hooks and publish an updated release.

Can I use ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION?

No. GitHub states the temporary override is no longer available after September 23.

Can a GitHub action with runs.using: node20 still execute?

GitHub clarified in November that the runner executes even legacy-declared actions with Node 24. That does not guarantee their code remains compatible or that the Node 20 runtime is supported.

Which checkout and setup-node releases support Node 24?

Both official actions document the move in their v5 majors, with newer majors containing additional updates. Pick a release compatible with your runner and test before rollout.

What is the minimum self-hosted runner version?

For checkout v5 and setup-node v5, GitHub specifies v2.327.1 or later. Other actions and later features may require newer versions.

Which operating systems and architectures are affected?

GitHub says Node 24 is incompatible with macOS 13.4 and older and does not officially support ARM32, so those self-hosted configurations are no longer supported in this change.

Why did GitHub move away from Node 20?

Node 20 reached upstream end of life in March 2026. Maintaining an unsupported runtime increases security and dependency risks; GitHub moved action execution to supported Node 24.

How should a team verify its migration?

Audit all action dependencies and runner platforms, test the packaged action under Node 24, run real workflow smoke tests, inspect logs and protect privileged workflow permissions.

Official sources, verification notes and editorial disclosure

Source review: November 8, 2026. GitHub's September 23 announcement is the primary news source; the earlier schedule explains the cutoff, and the November 4 GitHub staff comment clarifies temporary binary packaging. This article distinguishes officially supported JavaScript-action execution from application Node versions installed in workflow steps. The SXF seven-gate process is original analysis, not a claim of firsthand tests or a certification by GitHub. Example YAML and shell commands are educational and must be tested in each repository.

  1. GitHub Changelog — Node 20 is no longer available in GitHub Actions (September 23, 2026). Final policy, required migration and unsupported platforms.
  2. GitHub Changelog — Node 20 deprecation (2025, updated August 2026). Rollout dates, temporary exception and amended deadlines.
  3. GitHub Docs — Action metadata syntax. runs.using and supported action declaration examples.
  4. GitHub actions/setup-node README. Internal runtime changes, project node-version handling and runner requirements.
  5. GitHub actions/checkout README. v5 Node 24 upgrade and subsequent version notes.
  6. GitHub Docs — Self-hosted runner requirements. Supported host and runner update policy.
  7. GitHub runner-team comment (November 4). Why retained Node 20 binaries do not imply supported Node 20 execution.
  8. Node.js — Official release schedule. Node 20 EOL date and Node 24 LTS status.
  9. Node.js — End-of-life policy. Security implications of unsupported release lines.
  10. GitHub Docs — Secure use of GitHub Actions. Supply-chain and token-permission precautions.
  11. GitHub Docs — Workflow dependency lockfiles. Action integrity, immutable references and transitive dependencies.

For additional SXF context, explore Actions Runner Controller, GitHub permissions, AI agent security, automation reliability and all developer signals.

TOPICSNo topic tag yet
MODELSNo named model detected