openclaw - ✅(Solved) Fix pnpm build fails on ARM64: native ELF binary set as npm_execpath [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#64554Fetched 2026-04-11 06:14:27
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
cross-referenced ×1

Error Message

SyntaxError: Invalid or unexpected token at wrapSafe (node:internal/modules/cjs/loader:1637:18)

Root Cause

In scripts/pnpm-runner.mjs, the resolvePnpmRunner() function checks if npm_execpath matches a pnpm binary name pattern and then runs node <npm_execpath>. On platforms where pnpm ships as a native binary (ARM64 Linux), this results in Node trying to parse an ELF executable as JavaScript.

The pnpm shell shim at ~/.local/share/pnpm/pnpm works fine (it delegates to the native binary), but pnpm sets npm_execpath to the native binary itself, not the shim.

Fix Action

Workaround

Run individual build steps directly with node instead of through pnpm build. The build succeeds when each step is invoked independently.

PR fix notes

PR #64575: Fix/pnpm native binary support

Description (problem / solution / changelog)


Description

Problem

On platforms where pnpm (v10+) ships as a native ELF binary (such as ARM64 Linux/Raspberry Pi), the project's build scripts fail with a SyntaxError: Invalid or unexpected token.

This occurs because pnpm-runner.mjs assumes npm_execpath always points to a JavaScript file. When the runner attempts to execute node <npm_execpath>, Node.js tries to parse the ELF binary's magic bytes (0x7f 45 4c 46) as JavaScript code, leading to an immediate crash.

References

Fixes #64554

Solution

This PR introduces a more robust way to resolve and execute the pnpm runner:

  1. Binary Detection in pnpm-runner.mjs:
    • Added a check to verify if the file pointed to by npm_execpath is a JavaScript file based on its extension.
    • If it is a native binary, the runner now executes the binary path directly instead of wrapping it with the node executable.
  2. Environment Sanitization in build-all.mjs:
    • Added a sanitizeEnv utility to ensure that when child processes are spawned, they don't inherit a npm_execpath that points to a native binary.
    • This prevents nested execution failures where child tools might internally attempt to call node $npm_execpath.

How to Test

  1. Environment: Raspberry Pi (ARM64) or any Linux ARM64 environment.
  2. Version: pnpm v10.32.1 or higher.
  3. Command: Run pnpm build.
  4. Expected Result: The build should proceed through all steps without throwing a SyntaxError.

Notes

This change is backwards compatible. On Windows or x86 systems where pnpm still uses a JS-based shim or a .cmd file, the existing logic remains intact.


Changed files

  • scripts/build-all.mjs (modified, +32/-4)
  • scripts/pnpm-runner.mjs (modified, +32/-6)

Code Example

/home/MCServer1/.local/share/pnpm/.tools/@pnpm+linux-arm64/10.32.1/node_modules/@pnpm/linux-arm64/pnpm

---

SyntaxError: Invalid or unexpected token
    at wrapSafe (node:internal/modules/cjs/loader:1637:18)

---

function isNativeBinary(filePath) {
  try {
    const fs = require("node:fs");
    const fd = fs.openSync(filePath, "r");
    const buf = Buffer.alloc(4);
    fs.readSync(fd, buf, 0, 4, 0);
    fs.closeSync(fd);
    // ELF, Mach-O, PE magic bytes
    return (
      (buf[0] === 0x7f && buf[1] === 0x45 && buf[2] === 0x4c && buf[3] === 0x46) ||
      (buf[0] === 0xfe && buf[1] === 0xed) ||
      (buf[0] === 0x4d && buf[1] === 0x5a)
    );
  } catch { return false; }
}
RAW_BUFFERClick to expand / collapse

Environment

  • OS: Linux 6.1.21-v8+ (ARM64/aarch64) on Raspberry Pi
  • Node: v22.22.1
  • pnpm: 10.32.1 (native ARM64 binary)
  • OpenClaw: 2026.4.10 (a8bb0ab)

Problem

Running pnpm build fails because pnpm 10.32.1 sets npm_execpath to its native ELF binary path:

/home/MCServer1/.local/share/pnpm/.tools/@pnpm+linux-arm64/10.32.1/node_modules/@pnpm/linux-arm64/pnpm

When build scripts (e.g., build-all.mjs) spawn child pnpm processes, pnpm internally tries to run node <npm_execpath> to execute lifecycle scripts. Since the path points to a native ELF binary, Node fails with:

SyntaxError: Invalid or unexpected token
    at wrapSafe (node:internal/modules/cjs/loader:1637:18)

The ELF header bytes (0x7f 0x45 0x4c 0x46) cannot be parsed as JavaScript.

Root Cause

In scripts/pnpm-runner.mjs, the resolvePnpmRunner() function checks if npm_execpath matches a pnpm binary name pattern and then runs node <npm_execpath>. On platforms where pnpm ships as a native binary (ARM64 Linux), this results in Node trying to parse an ELF executable as JavaScript.

The pnpm shell shim at ~/.local/share/pnpm/pnpm works fine (it delegates to the native binary), but pnpm sets npm_execpath to the native binary itself, not the shim.

Workaround

Run individual build steps directly with node instead of through pnpm build. The build succeeds when each step is invoked independently.

Suggested Fix

pnpm-runner.mjs could detect native binaries by reading the first 4 bytes of the file and falling back to shell invocation:

function isNativeBinary(filePath) {
  try {
    const fs = require("node:fs");
    const fd = fs.openSync(filePath, "r");
    const buf = Buffer.alloc(4);
    fs.readSync(fd, buf, 0, 4, 0);
    fs.closeSync(fd);
    // ELF, Mach-O, PE magic bytes
    return (
      (buf[0] === 0x7f && buf[1] === 0x45 && buf[2] === 0x4c && buf[3] === 0x46) ||
      (buf[0] === 0xfe && buf[1] === 0xed) ||
      (buf[0] === 0x4d && buf[1] === 0x5a)
    );
  } catch { return false; }
}

Additionally, build-all.mjs and bundle-a2ui.mjs could strip npm_execpath from process.env before spawning child processes when it points to a native binary.

Reproduction

  1. Install pnpm 10.32.1 on ARM64 Linux (Raspberry Pi)
  2. Clone openclaw repo and run pnpm install
  3. Run pnpm build
  4. Observe SyntaxError: Invalid or unexpected token at the first pnpm lifecycle step

extent analysis

TL;DR

Modify the pnpm-runner.mjs to detect native binaries and use shell invocation instead of running node <npm_execpath> directly.

Guidance

  • Check if npm_execpath points to a native binary by reading the file's magic bytes, and if so, use the pnpm shell shim instead of the native binary.
  • Update build-all.mjs and bundle-a2ui.mjs to strip npm_execpath from process.env before spawning child processes when it points to a native binary.
  • Consider implementing the isNativeBinary function as suggested to detect native binaries.
  • Verify the fix by running pnpm build and checking if the SyntaxError is resolved.

Example

function resolvePnpmRunner() {
  const npmExecPath = process.env.npm_execpath;
  if (isNativeBinary(npmExecPath)) {
    // Use the pnpm shell shim
    return '/usr/local/bin/pnpm';
  }
  return npmExecPath;
}

Notes

  • This fix assumes that the pnpm shell shim is installed and functional on the system.
  • The isNativeBinary function may need to be updated to detect other types of native binaries.

Recommendation

Apply the suggested fix to modify pnpm-runner.mjs to detect native binaries and use shell invocation, as this should resolve the SyntaxError issue without requiring an upgrade to a fixed version of pnpm.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING