Skip to content

fix(exe): drop darwin-x64 artifact (upstream Node SEA bug)#11455

Merged
zkochan merged 4 commits into
mainfrom
drop/darwin-x64-broken-sea
May 4, 2026
Merged

fix(exe): drop darwin-x64 artifact (upstream Node SEA bug)#11455
zkochan merged 4 commits into
mainfrom
drop/darwin-x64-broken-sea

Conversation

@zkochan

@zkochan zkochan commented May 4, 2026

Copy link
Copy Markdown
Member

Summary

Closes #11423.

pnpm-darwin-x64.tar.gz and @pnpm/macos-x64 are removed because the binaries they contain segfault at startup on Intel Macs and the underlying bug is upstream and unfixed.

Why this isn't a fix in code

The crash happens in __cxx_global_var_init with EXC_BAD_ACCESS (code=1, address=0x3) — the unprocessed-chain-entry tag — in dyld's chained-fixup processing. PR #11415's hypothesis was that ldid's page hashes were the cause, but switching to native codesign in #11415 didn't fix it: the upstream minimal repro in nodejs/node#62893 is node --build-sea + codesign --sign - + run, with no pnpm and no ldid, and it still crashes. The corruption is in LIEF's Mach-O surgery during --build-sea for x64 — chained-fixup chain entries get rewritten incorrectly when the SEA segment is inserted, and re-signing produces a valid signature over the broken bytes.

The Node.js team is not going to fix this:

  • nodejs/node#60250 (merged) — "It's unlikely that anyone would invest in fixing them on x64 macOS in the near future, now that x64 macOS is being phased out." They skipped the SEA tests on x64 macOS rather than chase the bug.
  • nodejs/node#59553 (open) — long-running test failures on macOS x64 with the same root cause (sometimes surfacing as unsupported thread-local, larger than 4GB).

@yao-pkg/pkg works around it by appending the JS payload to the file tail and using a custom-patched Node binary that reads from the tail at startup; this avoids Mach-O surgery entirely. We can't reuse pack-app for that because vanilla Node from nodejs.org doesn't read tail-appended payloads — only pkg-fetch's patched binaries do — so adopting that path would mean re-implementing pkg-fetch for one target. For now we're dropping the broken artifact rather than introducing a second build mechanism.

Changes

  • pnpm/artifacts/exe/package.json — remove @pnpm/macos-x64 from optionalDependencies; remove darwin-x64 from pnpm.app.targets.
  • .meta-updater/src/index.ts — remove @pnpm/macos-x64 from the enforced optionalDependencies list (otherwise meta-updater would put it back).
  • pnpm/artifacts/exe/scripts/build-artifacts.ts — drop darwin-x64 from narrowTargets so dev-local builds match the published matrix; comment explains why.
  • __utils__/scripts/src/copy-artifacts.ts — stop creating pnpm-darwin-x64.tar.gz so the GitHub release page no longer ships it.
  • pnpm/artifacts/darwin-x64/ — deleted (was the workspace source for @pnpm/macos-x64).
  • pnpm/artifacts/exe/setup.js — wraps the import.meta.resolve('${pkgName}/package.json') lookup in try/catch. On Intel Mac specifically, prints a clear message pointing at this issue, the upstream Node.js issue, and the two workarounds (npm install -g pnpm to use the system Node.js, or stay on pnpm 10.x). Other unsupported hosts get a generic message in the same shape. Exits non-zero so the install fails loudly instead of silently leaving a broken pnpm.
  • pnpm-lock.yaml — regenerated.
  • .changeset/drop-darwin-x64-broken-sea.md — patch bumps for @pnpm/exe and pnpm with user-facing explanation and pointers.

Docs side already lists this limitation under pack-app Known limitations: pnpm/pnpm.io@36d962f6 / pnpm/pnpm.io@91f45632.

Compat

  • Intel Mac users on existing @pnpm/exe (≤ 11.0.4) keep working with the (broken) old binary they already have.
  • pnpm self-update from an Intel Mac on an older @pnpm/exe will hit the new setup.js error path with a clear pointer to the workarounds.
  • New Intel Mac installs via npm install -g @pnpm/exe will fail loudly with the same pointer.
  • Install via npm install -g pnpm (the JS-only package, uses system Node) is unaffected and remains the recommended path.
  • The install.sh from get.pnpm.io will fail with a 404 on the missing pnpm-darwin-x64.tar.gz. That's a separate repo and a follow-up — happy to do that as a second PR.

Test plan

  • pnpm install regenerates the lockfile cleanly; only the @pnpm/exe importer's @pnpm/macos-x64 link is removed.
  • pnpm run spellcheck passes.
  • pnpm run lint:meta (which runs meta-updater --test to check workspace manifest sync) passes.
  • setup.js syntax-checks (node --check); preinstall on Apple Silicon (darwin-arm64) still resolves the platform package and links the binary, so the new error path is correctly scoped to missing-platform-package only.
  • Manual verification on Intel Mac that npm install -g @pnpm/exe fails with the new error message (no Intel hardware available locally — would appreciate a maintainer with one running this).
  • After merge, verify the next release page only lists 7 binary tarballs (no pnpm-darwin-x64.tar.gz).

Follow-ups (separate PRs)

  • Update get.pnpm.io/install.sh to detect darwin-x64 and print a clear "not supported" message before attempting download.
  • Decide whether to publish a final empty/error-only @pnpm/macos-x64 placeholder so old @pnpm/exe installs that resolve latest get a clear runtime message rather than the cached broken binary.

References

Summary by CodeRabbit

  • Chores
    • Removed the darwin-x64 (Intel Mac) executable from release artifacts and GitHub releases due to a Node.js binary compatibility issue causing runtime crashes.
    • Updated release metadata and patch versions for the installer artifacts.
    • Updated alternative installation guidance for Intel Mac users: use npm install -g pnpm (system Node.js) or remain on pnpm 10.x.
    • Enhanced preinstall error messaging to clearly direct Intel Mac users to recommended alternatives.
    • Closed the related tracking issue.

Node.js SEA injection produces a binary that segfaults at startup on
Intel Macs. The bug is in LIEF's Mach-O surgery during --build-sea, not
in signing — the canonical `node --build-sea` + `codesign --sign -` flow
crashes too (nodejs/node#62893). The Node.js team has opted not to fix
it (nodejs/node#60250) on the grounds that x64 macOS is being phased
out; long-running test failures are tracked in nodejs/node#59553.

Changes:

- Remove `@pnpm/macos-x64` from `@pnpm/exe`'s optionalDependencies and
  from the meta-updater enforcement list, so npm no longer tries to
  install the broken platform package on Intel Mac.
- Remove `darwin-x64` from `pnpm.app.targets` and from `narrowTargets`
  in build-artifacts.ts so pack-app skips the build entirely.
- Remove the `darwin-x64` tarball from copy-artifacts.ts so
  `pnpm-darwin-x64.tar.gz` is no longer produced for the GitHub release.
- Delete the `pnpm/artifacts/darwin-x64` workspace package (was the
  source of `@pnpm/macos-x64`).
- `setup.js` now wraps the `import.meta.resolve(...)` for the platform
  package in try/catch and, on Intel Mac, prints a clear pointer to
  this issue plus workarounds (npm install -g pnpm, or pnpm 10.x)
  before exiting non-zero. Other unsupported platforms get a generic
  message in the same shape.

Closes #11423.
Copilot AI review requested due to automatic review settings May 4, 2026 16:53
@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR removes the darwin-x64 (@pnpm/macos-x64) artifact and build target due to a Node.js SEA-injected binary that segfaults on Intel Macs, stops generating the darwin-x64 tarball, updates platform optionalDependencies, adds guarded setup/preinstall error handling with a workspace-aware exit path and Intel‑macOS-specific message, and adds tests for the failure paths.

Changes

Darwin-x64 artifact removal and installer behavior

Layer / File(s) Summary
Release Documentation
.changeset/drop-darwin-x64-broken-sea.md
Marks patch releases and documents removal of darwin-x64 from @pnpm/exe releases, explains Intel Mac SEA segfault and provides alternative install guidance; closes #11423.
Artifact removal (files deleted/cleaned)
pnpm/artifacts/darwin-x64/*
Removed the @pnpm/macos-x64 artifact manifest and related files (package.json, CHANGELOG.md entry, README.md, .gitignore, .npmignore).
Artifact packaging step
__utils__/scripts/src/copy-artifacts.ts
Stops creating the darwin-x64 tarball; comment added noting intentional omission due to Intel Mac SEA segfault.
Build target selection
pnpm/artifacts/exe/scripts/build-artifacts.ts
Removed darwin-x64 from narrowed host targets (now ['win32-x64','linux-x64']) and updated explanatory comments; buildFullMatrix logic unchanged.
Package manifest / optional deps
pnpm/artifacts/exe/package.json,
.meta-updater/src/index.ts
Dropped @pnpm/macos-x64 from optionalDependencies and removed darwin-x64 from pnpm.app.targets; meta-updater added @pnpm/linuxstatic-arm64 and @pnpm/linuxstatic-x64 to platform optionalDependencies.
Setup / preinstall error handling
pnpm/artifacts/exe/setup.js
Wraps platform package resolution in try/catch; on ERR_MODULE_NOT_FOUND exits 0 for workspace-shaped runs, otherwise prints platform-specific missing-package message (special-case for darwin-x64 referencing the SEA bug) and exits 1; non-resolution errors are rethrown.
Tests (failure-paths)
pnpm/artifacts/exe/test/setup.test.ts
Adds sandbox helper and two spawn-based tests validating workspace silent-exit and non-workspace non-zero exit with expected stderr message; tests skip on Windows where symlink creation is privileged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • pnpm/pnpm#11446: Related — also addresses the darwin-x64 Node.js SEA crash and updates release workflow commentary.
  • pnpm/pnpm#11415: Related — addresses darwin-x64 startup/signing/build issues on Intel macOS.

Poem

🐰
I found a wobbly binary that made Intel Macs cry,
So I trimmed the targets and let the broken one lie.
Choose a different install or linger on ten for now—
A clear message hops out; we fixed the how.
Thump, patch, release — carrots for the prow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(exe): drop darwin-x64 artifact (upstream Node SEA bug)' accurately summarizes the main change: removing the darwin-x64 binary artifact due to a Node.js SEA (Single Executable Application) bug that causes segfaults on Intel Macs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drop/darwin-x64-broken-sea

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the darwin-x64 (@pnpm/macos-x64 / pnpm-darwin-x64.tar.gz) standalone executable artifact from @pnpm/exe distribution, due to an upstream Node.js SEA bug causing consistent crashes on Intel macOS, and adds a clearer install-time failure message for Intel Macs.

Changes:

  • Remove @pnpm/macos-x64 optional dependency and darwin-x64 build target from @pnpm/exe.
  • Update build/release artifact generation scripts to stop producing pnpm-darwin-x64.tar.gz and to align local/CI target matrices.
  • Improve @pnpm/exe preinstall (setup.js) behavior when the platform package is missing by printing actionable guidance and exiting non-zero.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pnpm/artifacts/exe/setup.js Wrap platform package resolution in try/catch and emit a targeted Intel macOS error message when the platform package isn’t present.
pnpm/artifacts/exe/scripts/build-artifacts.ts Remove darwin-x64 from Intel-Mac “narrow” targets and update rationale comments.
pnpm/artifacts/exe/package.json Drop @pnpm/macos-x64 from optionalDependencies and remove darwin-x64 from pnpm.app.targets.
__utils__/scripts/src/copy-artifacts.ts Stop producing the pnpm-darwin-x64 release tarball and document why.
.meta-updater/src/index.ts Prevent meta-updater from re-introducing @pnpm/macos-x64 into enforced optional deps.
pnpm/artifacts/darwin-x64/* Delete the @pnpm/macos-x64 workspace package sources.
pnpm-lock.yaml Regenerate lockfile to remove the deleted workspace importer and links.
.changeset/drop-darwin-x64-broken-sea.md Add changeset documenting the removal and user guidance.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/artifacts/exe/setup.js
Comment thread pnpm/artifacts/exe/setup.js Outdated
Comment thread pnpm/artifacts/exe/setup.js Outdated
Address Copilot review on #11455:

- Catch only ERR_MODULE_NOT_FOUND from import.meta.resolve and rethrow
  anything else, so unrelated resolver failures surface instead of being
  reported as "unsupported host."
- When running inside the pnpm workspace itself (detected via an
  ancestor pnpm-workspace.yaml), skip the hard error and exit 0. Without
  this, a contributor on Intel macOS — where the platform package was
  removed in the parent commit — could no longer `pnpm install` the
  repo to work on unrelated parts of pnpm.
- Reword the awkward "doesn't ship a binary for is darwin-x64" comment.

Verified isInPnpmWorkspace returns true from inside the workspace and
false from /tmp / a typical global install path. Verified import.meta.resolve
throws ERR_MODULE_NOT_FOUND on a missing package.
Replace the ancestor `pnpm-workspace.yaml` walk-up with a precise
suffix check on `import.meta.dirname` (must end in `pnpm/artifacts/exe`,
the workspace path of @pnpm/exe).

The walk-up could false-positive: a user globally installing @pnpm/exe
while their cwd or install path happened to live under any unrelated
pnpm workspace tree would be misidentified as a workspace contributor
and silently skipped, leaving them with no working pnpm. The
suffix-on-the-script's-own-directory check matches only when this
script is literally the workspace's @pnpm/exe.

Verified with sample paths: workspace clones (any disk location) match,
global/local installs and contrived "artifacts/exe" paths without the
"pnpm/" segment do not.
Copilot AI review requested due to automatic review settings May 4, 2026 18:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/artifacts/exe/scripts/build-artifacts.ts Outdated
Comment thread pnpm/artifacts/exe/setup.js
…h tests

Address Copilot review on #11455 (round 2):

- build-artifacts.ts: the comment said "On Intel Mac we only build the
  two baseline targets" but `buildFullMatrix` is `linux || isM1Mac`,
  so any non-Linux non-Apple-Silicon host (Windows, Intel Mac, etc.)
  uses narrowTargets. Reword to match the actual condition and keep
  the darwin-x64-absent rationale.

- setup.test.ts: add two integration tests that stand up a minimal
  sandbox (setup.js + platform-pkg-name.js + a node_modules with only
  detect-libc symlinked from this repo) at a tempdir whose path either
  ends in `pnpm/artifacts/exe` (workspace shape) or doesn't (global-
  install shape). import.meta.resolve for the host's platform package
  fails in both because no @pnpm/<platform> is installed. Asserts:
    1. workspace-shaped path → exit 0, no stderr
    2. non-workspace path    → exit 1, stderr names the missing pkg
  Verified the workspace-shape test fails when the path-suffix in
  setup.js is mutated (i.e. the test isn't a no-op). Skipped on
  Windows because fs.symlinkSync there needs elevated privileges and
  the path-suffix logic is platform-independent.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pnpm/artifacts/exe/test/setup.test.ts (1)

99-116: ⚡ Quick win

Move buildFailurePathSandbox below its call sites to match repo function-order convention.

This helper is declared before usage. In this repo, function declarations should be placed after use (relying on hoisting).

As per coding guidelines, **/*.{ts,tsx,js,jsx}: "declare functions after they are used (relying on hoisting)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpm/artifacts/exe/test/setup.test.ts` around lines 99 - 116, The helper
function buildFailurePathSandbox is declared before it's used; per repo
convention functions should be declared after their call sites (relying on
hoisting). Move the entire buildFailurePathSandbox declaration so it appears
after all places that call it (search for buildFailurePathSandbox usage in this
test file) and ensure any required helper variables (exeDir, fs, path, os)
remain in scope; no other code changes are needed besides reordering the
declaration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pnpm/artifacts/exe/test/setup.test.ts`:
- Around line 99-116: The helper function buildFailurePathSandbox is declared
before it's used; per repo convention functions should be declared after their
call sites (relying on hoisting). Move the entire buildFailurePathSandbox
declaration so it appears after all places that call it (search for
buildFailurePathSandbox usage in this test file) and ensure any required helper
variables (exeDir, fs, path, os) remain in scope; no other code changes are
needed besides reordering the declaration.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6587b537-8f39-4a61-b7e7-da6d2e36a640

📥 Commits

Reviewing files that changed from the base of the PR and between 2906888 and d0e5161.

📒 Files selected for processing (2)
  • pnpm/artifacts/exe/scripts/build-artifacts.ts
  • pnpm/artifacts/exe/test/setup.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • pnpm/artifacts/exe/scripts/build-artifacts.ts

@zkochan zkochan merged commit 548208a into main May 4, 2026
13 checks passed
@zkochan zkochan deleted the drop/darwin-x64-broken-sea branch May 4, 2026 19:23
zkochan added a commit that referenced this pull request May 4, 2026
## Summary

Closes #11423.

`pnpm-darwin-x64.tar.gz` and `@pnpm/macos-x64` are removed because the binaries they contain segfault at startup on Intel Macs and the underlying bug is upstream and unfixed.

## Why this isn't a fix in code

The crash happens in `__cxx_global_var_init` with `EXC_BAD_ACCESS (code=1, address=0x3)` — the unprocessed-chain-entry tag — in dyld's chained-fixup processing. PR #11415's hypothesis was that `ldid`'s page hashes were the cause, but switching to native `codesign` in #11415 didn't fix it: the upstream minimal repro in [nodejs/node#62893](nodejs/node#62893) is `node --build-sea` + `codesign --sign -` + run, with no pnpm and no `ldid`, and it still crashes. The corruption is in LIEF's Mach-O surgery during `--build-sea` for x64 — chained-fixup chain entries get rewritten incorrectly when the SEA segment is inserted, and re-signing produces a valid signature over the broken bytes.

The Node.js team is not going to fix this:

- [nodejs/node#60250](nodejs/node#60250) (merged) — *"It's unlikely that anyone would invest in fixing them on x64 macOS in the near future, now that x64 macOS is being phased out."* They skipped the SEA tests on x64 macOS rather than chase the bug.
- [nodejs/node#59553](nodejs/node#59553) (open) — long-running test failures on macOS x64 with the same root cause (sometimes surfacing as `unsupported thread-local, larger than 4GB`).

`@yao-pkg/pkg` works around it by appending the JS payload to the file tail and using a custom-patched Node binary that reads from the tail at startup; this avoids Mach-O surgery entirely. We can't reuse pack-app for that because vanilla Node from nodejs.org doesn't read tail-appended payloads — only pkg-fetch's patched binaries do — so adopting that path would mean re-implementing pkg-fetch for one target. For now we're dropping the broken artifact rather than introducing a second build mechanism.

## Changes

- **`pnpm/artifacts/exe/package.json`** — remove `@pnpm/macos-x64` from `optionalDependencies`; remove `darwin-x64` from `pnpm.app.targets`.
- **`.meta-updater/src/index.ts`** — remove `@pnpm/macos-x64` from the enforced `optionalDependencies` list (otherwise `meta-updater` would put it back).
- **`pnpm/artifacts/exe/scripts/build-artifacts.ts`** — drop `darwin-x64` from `narrowTargets` so dev-local builds match the published matrix; comment explains why.
- **`__utils__/scripts/src/copy-artifacts.ts`** — stop creating `pnpm-darwin-x64.tar.gz` so the GitHub release page no longer ships it.
- **`pnpm/artifacts/darwin-x64/`** — deleted (was the workspace source for `@pnpm/macos-x64`).
- **`pnpm/artifacts/exe/setup.js`** — wraps the `import.meta.resolve('${pkgName}/package.json')` lookup in `try`/`catch`. On Intel Mac specifically, prints a clear message pointing at this issue, the upstream Node.js issue, and the two workarounds (`npm install -g pnpm` to use the system Node.js, or stay on pnpm 10.x). Other unsupported hosts get a generic message in the same shape. Exits non-zero so the install fails loudly instead of silently leaving a broken `pnpm`.
- **`pnpm-lock.yaml`** — regenerated.
- **`.changeset/drop-darwin-x64-broken-sea.md`** — patch bumps for `@pnpm/exe` and `pnpm` with user-facing explanation and pointers.

Docs side already lists this limitation under `pack-app` Known limitations: pnpm/pnpm.io@36d962f6 / pnpm/pnpm.io@91f45632.

## Compat

- Intel Mac users on existing `@pnpm/exe` (≤ 11.0.4) keep working with the (broken) old binary they already have.
- `pnpm self-update` from an Intel Mac on an older `@pnpm/exe` will hit the new `setup.js` error path with a clear pointer to the workarounds.
- New Intel Mac installs via `npm install -g @pnpm/exe` will fail loudly with the same pointer.
- Install via `npm install -g pnpm` (the JS-only package, uses system Node) is unaffected and remains the recommended path.
- The `install.sh` from `get.pnpm.io` will fail with a 404 on the missing `pnpm-darwin-x64.tar.gz`. That's a separate repo and a follow-up — happy to do that as a second PR.
@marr

marr commented Jun 3, 2026

Copy link
Copy Markdown

@zkochan since nodejs/node#62893 was closed, does that mean intel support on macs will be coming back to pnpm?

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.

pnpm 11.0.3 standalone executable segfaults on Intel macOS (upstream Node.js SEA bug)

3 participants