n8n 2.33.7 distroless fails with GLIBC_PRIVATE on ARM64 while 2.26.9 works on the same host - XBSTACK

n8n 2.33.7 Distroless ARM64 GLIBC_PRIVATE Error: Reproduction and Workaround

Release Date
2026-08-11
Reading Time
5 min
Content Size
6,635 chars
N8n
Arm64
Docker
Distroless
Glibc
Task Runner
Regression
Laboratory Note

Reproduced on 2026-08-11 with both host and Docker Server architecture set to arm64 under Docker Desktop. The test executes /opt/runners/task-runner-python/.venv/bin/python --version directly, without starting n8n, connecting a database, or calling a model API. Upstream issue #35913 remained open immediately before publication. This page verifies the published-image regression, the 2.26.9 rollback control, and the failure of a libc-only diagnostic; it does not claim a full Debian-aligned rebuild has been verified.

Who Should Read This

  • Self-hosted n8n users running distroless task runners on ARM64, Apple Silicon, ARM cloud VMs, or ARM Kubernetes nodes.
  • Operators who see GLIBC_PRIVATE, libc.so.6 symbol lookup errors, or exit 127 after upgrading the runners image.
  • Engineering teams that need a reproducible rollback decision and an ARM64 regression check before an upstream fixed release is available.

n8n 2.33.7 Distroless ARM64 GLIBC_PRIVATE Error: Reproduction and Workaround

If you upgrade the n8n distroless task runner to n8nio/runners:2.33.7-distroless, the Python runner can exit on ARM64 before any workflow logic runs. The failure looks like this:

/opt/runners/task-runner-python/.venv/bin/python: symbol lookup error: /lib/aarch64-linux-gnu/libc.so.6: undefined symbol: __tunable_is_initialized, version GLIBC_PRIVATE

I reduced the problem to a direct image test on Apple Silicon with Docker Desktop. No n8n server, database, model provider, or workflow is required. 2.33.7-distroless consistently exits 127; on the same host, changing only the image tag to 2.26.9-distroless prints Python 3.13.14. That means the first troubleshooting target should be the runner image and its runtime ABI, not a Code node, an AI Agent, or a workflow JSON export.

Immediately before publication on August 11, 2026, the official n8n issue #35913 was still open. The current Dockerfile.distroless also still exposes the relevant boundary: Python is built on Debian 12 slim-bookworm, the final runtime is Debian 13 cc-debian13, and architecture-specific libraries from the builder are copied into the runtime filesystem. That matches the glibc mismatch described upstream. I am not claiming that switching to trixie is already a verified permanent fix because I have not yet completed a full source rebuild of the n8n runners image with that alignment.

Confirm the failure with one command

On an ARM64 Docker host, run the Python entry point directly:

docker run --rm \
  --entrypoint /opt/runners/task-runner-python/.venv/bin/python \
  n8nio/runners:2.33.7-distroless \
  --version

Observed in this reproduction:

exit 127
/opt/runners/task-runner-python/.venv/bin/python: symbol lookup error: /lib/aarch64-linux-gnu/libc.so.6: undefined symbol: __tunable_is_initialized, version GLIBC_PRIVATE

This check intentionally bypasses workflows, credentials, model providers, databases, and the higher-level launcher path. If the Python executable itself cannot start, rebuilding a workflow or changing an AI node is the wrong first move.

Now run the same entry point against the working control on the same machine:

docker run --rm \
  --entrypoint /opt/runners/task-runner-python/.venv/bin/python \
  n8nio/runners:2.26.9-distroless \
  --version

Observed output:

Python 3.13.14

The measured matrix is therefore narrow and useful:

ImageARM64 resultExit
n8nio/runners:2.26.9-distrolessPython 3.13.140
n8nio/runners:2.33.7-distroless__tunable_is_initialized, version GLIBC_PRIVATE127
Derived 2.33.7 image replacing only Debian 13 libc.so.6same symbol lookup error127

Those are the three results this page independently verifies. They do not prove that every 2.33.x release, AMD64 image, or non-distroless build has the same failure.

Why the root-cause boundary points to mixed Debian/glibc generations

Before publishing, I re-read the current upstream docker/images/runners/Dockerfile.distroless. The relevant stages are still effectively:

FROM python:${PYTHON_VERSION}-slim-bookworm AS python-runner-builder
...
FROM debian:bookworm-slim AS runtime-prep
...
COPY --from=python-runner-builder /lib/*-linux-gnu* /runtime/usr/lib/
COPY --from=python-runner-builder /usr/lib/*-linux-gnu* /runtime/usr/lib/
...
FROM gcr.io/distroless/cc-debian13:latest AS runtime
COPY --from=runtime-prep --chown=root:root /runtime/ /

Python and some architecture-specific runtime libraries therefore come from a Debian 12/bookworm builder, while the final base is Debian 13 distroless. Issue #35913 describes the same generation boundary and the same GLIBC_PRIVATE lookup failure.

GLIBC_PRIVATE is also a strong clue: it is not a public stable ABI contract intended for mixing unrelated glibc builds. If a process loads an incompatible set of loader, libc, or related system libraries, it can fail during process startup before Python code executes.

The evidence boundary still matters. This reproduction proves that the published 2.33.7 image fails on the tested ARM64 host and that the Dockerfile mixes Debian generations across build/runtime boundaries. It does not independently prove that one specific copied library is the only root cause.

Replacing only libc.so.6 did not fix it

Because the error names libc.so.6, the obvious temptation is to copy Debian 13’s libc back into the image. I tested that as a narrow diagnostic control: derive from the broken 2.33.7-distroless image, copy Debian 13 libc.so.6 from gcr.io/distroless/cc-debian13, then rerun the exact same Python --version check.

The result did not change:

exit 127
undefined symbol: __tunable_is_initialized, version GLIBC_PRIVATE

That is useful negative evidence. It rules out a simplistic one-file patch as a verified repair. The runtime ABI needs to be treated as a coherent set rather than replacing whichever .so appears in the first error message. Without a full rebuilt image, I am not going to guess which additional loader or system-library files must be aligned.

The complete experiment, logs, machine-readable results, and version matrix are public here:

GitHub: xbstack/n8n-distroless-arm64-glibc-repro

Verified temporary recovery: roll back the runner image

In this ARM64 environment, the only short-term option that has passed the exact same entry-point test is:

n8nio/runners:2.26.9-distroless

If the symbol lookup error appeared only after a runner-image upgrade, a controlled rollback is a reasonable recovery candidate after you back up configuration, verify version-specific feature requirements, and rerun your own workflows.

The trade-off is important: 2.26.9 is older. Pinning it can mean missing later features, bug fixes, or security updates. Treat this as a temporary service-recovery workaround, not a long-term version policy. If your deployment requires functionality introduced after 2.26.9, the rollback may not be acceptable.

What would count as a verified permanent fix?

The upstream issue points toward aligning the Python builder and final distroless runtime on the same Debian generation—for example, moving the Python builder away from slim-bookworm toward a Debian 13-aligned base, or using a final runtime that matches the Debian 12 builder.

That direction is consistent with the ABI evidence, but plausible is not the same as verified. For XBSTACK to mark a permanent fix as tested, I want at least this regression set:

  1. rebuild the ARM64 runners image from current n8n source, rather than replacing one or two files in the published image;
  2. rerun the same Python --version command and see exit 127 become exit 0;
  3. verify task-runner-launcher can start the Python runner;
  4. confirm the JavaScript runner does not gain a new dynamic-library regression;
  5. execute at least one real Code/Python workflow end to end;
  6. map the passing build to an upstream PR or released version.

Until those checks pass, this page calls Debian-generation alignment an upstream fix direction, not a one-line confirmed solution.

Production troubleshooting order

If you are seeing this exact error, use this order:

  1. run the direct Python entry-point command to see whether the image itself already fails;
  2. record uname -m and Docker Server architecture and confirm whether the host is ARM64;
  3. record the exact runner tag instead of saying only “latest”;
  4. run a known-good image on the same host to separate image regression from host configuration;
  5. if you need to restore service quickly, evaluate a rollback to a version you have tested instead of copying glibc files by hand;
  6. follow issue #35913 for a PR/release and rerun the same minimal command before upgrading again.

Do not automatically apply this conclusion if your error occurs in the main n8n server, on AMD64, in a non-distroless runner, or with a different symbol string. Similar libc.so.6 errors can have different causes.

Upstream status and update boundary

As of publication on August 11, 2026:

  • n8n issue #35913: Open;
  • XBSTACK ARM64 reproduction of the published 2.33.7 image: complete;
  • same-host 2.26.9 working control: complete;
  • Debian 13 libc.so.6 single-file replacement: confirmed insufficient;
  • full Debian-aligned runners rebuild: not yet completed;
  • official fixed release: not yet verified in this environment.

If n8n merges a fix or publishes a new runner image, I will rerun the same ARM64 entry-point regression before changing this page from “reproduction + workaround” to “permanent fix verified.”

Topic path / AI workflows

Continue through the production automation path

The workflow hub connects self-hosting, queue mode, webhooks, retries, observability and n8n implementation cases into one production-oriented learning path.

Next Reading

View Hub →
Xiaobai

Xiaobai

Full-Stack AI Engineer

Xiaobai, a full-stack AI engineer building production Agent systems, product tools and independent software assets.

About Xiaobai & XBSTACK →

Liked this article?
Join the newsletter

Every issue condenses production AI engineering changes, real failures, reproducible experiments, useful tools and new XBSTACK assets. No generic news digest and no filler.

Comments

DISCUSSION

Questions, verification and corrections

Sign in to comment. Every new comment is reviewed before publication; while pending, it is visible only to you and the administrator.

Sign-in required Reviewed before public
Loading the discussion…