Skip to content

Install libatomic so Node.js 25+ works in the runner image and on self-hosted Linux runners - #4640

Open
yooknee wants to merge 2 commits into
actions:mainfrom
yooknee:main
Open

Install libatomic so Node.js 25+ works in the runner image and on self-hosted Linux runners#4640
yooknee wants to merge 2 commits into
actions:mainfrom
yooknee:main

Conversation

@yooknee

@yooknee yooknee commented Aug 17, 2026

Copy link
Copy Markdown

Fixes #4591

Problem

The official Node.js binaries link against libatomic.so.1 starting with Node.js 25. Neither
the mcr.microsoft.com/dotnet/runtime-deps:8.0-noble base image nor a stock Debian/Ubuntu host
ships that library, so any workflow step that provisions a modern Node — most commonly
actions/setup-node — installs successfully and then fails the moment Node is executed:

Installing Node is a routine workflow step, so the runner should supply the library rather than
leaving every user to discover the workaround themselves.

Verification

readelf -d bin/node on the official tarballs pins the cutover at Node 25, on both architectures:

Node build libatomic.so.1 in NEEDED
v24.18.1 linux-x64 (currently bundled in externals/) no
v24.19.0 linux-x64 no
v25.9.0 linux-x64 yes
v26.7.0 linux-x64 yes
v26.7.0 linux-arm64 yes

The base image installs only ca-certificates, libc6, libgcc-s1, libicu74, libssl3t64, libstdc++6, tzdata, tzdata-legacy, zlib1glibatomic1 is genuinely absent.

Changes

images/Dockerfilelibatomic1 added to the existing apt transaction in the runtime stage,
not a new RUN, so the layer count is unchanged and the existing rm -rf /var/lib/apt/lists/*
still applies.

.github/workflows/build.yml — regression test in the docker job so the library cannot
silently drop out of the image again. It runs on both the amd64 and arm64 matrix legs:

docker run --rm <image> bash -c 'set -euo pipefail; "$(command -v ldconfig || echo /sbin/ldconfig)" -p | grep -F -- "libatomic.so.1"'

@yooknee
yooknee requested a review from a team as a code owner August 17, 2026 09:19
claude added 2 commits August 18, 2026 10:44
The official Node.js binaries link against libatomic.so.1 starting with
Node.js 25 (confirmed with `readelf -d bin/node`: the NEEDED entry is
absent in v24.x and present in v25.x and v26.x, on both linux-x64 and
linux-arm64). The dotnet/runtime-deps base image does not ship that
library, so a workflow that provisions Node with actions/setup-node fails
at exec time with:

  node: error while loading shared libraries: libatomic.so.1:
  cannot open shared object file: No such file or directory

Add libatomic1 to the existing apt transaction in the runtime stage. It
comes from Ubuntu main (source package gcc-14), so it adds no new
repository or trust anchor, ships no executables, and costs ~50 kB
installed. Reusing the existing RUN keeps the layer count unchanged and
keeps the package lists cleaned up in the same step.

Also add a cheap regression test to the docker job so the library cannot
silently disappear from the image again.

Fixes actions#4591
Non-containerized self-hosted runners hit the same Node.js 25+ failure as
the container image: actions/setup-node installs Node into the tool cache,
and it cannot start without libatomic.so.1.

Install the library from each distribution's own package manager
(libatomic1 on Debian/SUSE based, libatomic on Fedora based). This is done
best-effort rather than as a hard requirement: the runner itself does not
need libatomic today, since the bundled externals/node20 and
externals/node24 do not link against it, so a distribution that does not
package it must still configure successfully. On failure the script prints
an actionable warning naming the package and the error it prevents.

For the same reason config.sh is left alone -- gating runner configuration
on a library only future Node.js versions need would be a regression.

Document the dependency and the reasoning in docs/start/envlinux.md.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Node v26 not working in Docker image after installing Node due to missing libatomic

2 participants