Skip to content

Pin Electron to 43.6.0: 43.7.0 and later crash the dev server on Apple Silicon - #539

Merged
zaerl merged 2 commits into
trunkfrom
fix/pin-electron-43-6
Sep 28, 2026
Merged

zaerl merged 2 commits into
trunkfrom
fix/pin-electron-43-6

Conversation

@zaerl

@zaerl zaerl commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Why

Since #537 moved Electron from 43.2.0 to 43.7.5, clicking Start dev server on an Apple Silicon Mac fails within about a second. The log reads server exited with code null (signal SIGBUS) and macOS files a crash report for the Electron Helper running the Playground server: EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, on a V8Worker thread. The 1.2.0 release is unaffected because it shipped 43.2.0, but anything built from trunk since #537 has a dead dev server on macOS.

What changes

Electron is pinned to 43.6.0, the last release that runs the server, and the allowScripts key follows. The pin is exact rather than a caret range so a later npm update cannot walk back onto 43.7.x. The lockfile diff is electron only.

Root cause. Running src/server-runner.js directly on each Electron Helper as Node, five times each, bisects the crash to 43.7.0:

Runtime Result
Electron 43.2.0, 43.3, 43.4, 43.5.1, 43.6.0 starts, 5/5
Electron 43.7.0, 43.7.5 SIGBUS, 5/5
Plain Node 24.21.0, the Node 43.7.0 bumped to starts
Playground CLI 3.1.47 or 3.1.56 on 43.2.0 starts
Playground CLI 3.1.47 or 3.1.56 on 43.7.5 SIGBUS
43.7.5 with V8 flag --liftoff-only starts, 5/5
43.7.5 with --no-liftoff, --single-threaded, --no-wasm-dynamic-tiering SIGBUS

Plain Node and the Playground CLI are cleared, so the cause is in the V8 backports 43.7.0 carries (electron/electron#53766). The one that fits is [wasm][sandbox] Fix side effects of WasmGetOwnProperty builtin, which changes Liftoff and the Turboshaft wasm compiler, and php.wasm exports a WebAssembly exception tag, which that builtin serves. The flag results say the crash needs V8's optimizing wasm compiler and never happens under Liftoff alone.

Deliberately not done. Passing --liftoff-only to the server spawn would also work, but it keeps PHP on the baseline compiler and papers over a V8 bug. Electron 44 was not tested: fs-ext-extra-prebuilt has no prebuilt for its ABI, which is a separate blocker for that upgrade.

How to test this

Platforms: macOS on Apple Silicon, because the crash was only observed there. Windows is covered by CI and should behave as before. Use the Buildkite artifact for this branch at the current head, or run from source.

Starting state: a site that has finished its full build, on macOS, with the current head installed. From the repository root, npm install and confirm it reports electron 43.6.0:

node -e 'console.log(require("./node_modules/electron/package.json").version)'
  1. Run npm start, open the site, and click Start dev server. Expected: within a few seconds the button turns into Stop dev server and a 127.0.0.1 URL appears.
  2. Open the URL. Expected: the WordPress front page renders.
  3. Click Stop dev server. Expected: the button returns to Start dev server.

What must not have happened:

  • server exited with code null (signal SIGBUS) in the runtime log or in Help → Open App Log.
  • A new Electron Helper-*.ips file in ~/Library/Logs/DiagnosticReports/.

The same failure, and its fix, can be driven without the UI. From the repository root, with SITE set to a built site's folder:

ELECTRON_RUN_AS_NODE=1 "node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Helper.app/Contents/MacOS/Electron Helper" src/server-runner.js "{\"strategy\":\"docroot\",\"docroot\":\"$SITE/build\"}"

On trunk this exits with SIGBUS in about a second. On this branch it prints SERVER_URL: and keeps running.

What cannot be tested by hand: the exact V8 commit. Electron ships no debug symbols for 43.x, so the attribution to the WasmGetOwnProperty backport rests on the bisect and the flag results, not on a symbolised stack.

Risks and limitations

  • This gives up the 43.7.x security backports. The Chromium version is the same on both sides (150.0.7871.250, since 43.5.1); the delta is the patch batches from 2026-09-10 to 2026-09-23. The app does execute one remote page: the Trac ticket window in src/trac-view.js runs Trac's proof-of-work JavaScript, sandboxed, context-isolated, without preload, on its own partition and pinned to the https origin. The self-review checked each enumerated 43.7.x fix against the source and found none reachable through that or any other surface the app has. It is a [follow-up], not a [fix here]: there is no version that is both working and current. The pin should be lifted at the first 43.x or 44.x release that starts the server.
  • No automated test catches this, and this PR does not add one. A bare php-wasm run, light or heavy, does not crash on 43.7.0; only the full Playground boot against a real WordPress build does, and an empty docroot fails cleanly on the database instead. So a layer-2 test cannot reach it without a wordpress-develop build, and the honest home is the existing real-setup.yml lane. AGENTS.md now records the ceiling and its reason next to the pin, and TESTING.md says that workflow is the only test that starts the server and must run on Electron bumps. The manual check for this PR was the direct runner start on an Apple Silicon Mac, 5 of 5. Making real-setup.yml run automatically on changes to the electron version is the durable fix and is left as a follow-up.
  • Electron 43.6.0 bundles Node 24.20.0 against .nvmrc's 24.18.0, so the system Node stays the older of the two; both unit runs pass.

Related

Regression from #537. Upstream report to Electron to follow, with the bisect above.


Design decisions and alternatives considered
  • Pin to 43.6.0 rather than 43.2.0. 43.6.0 is the last good release and carries the 43.3 to 43.6 fixes, including the node:wasi and node::ObjectWrap crash fixes and Node 24.20.0. Nothing between 43.2.0 and 43.6.0 crashed in the bisect.
  • Exact pin rather than ~43.6.0. There is no 43.6.1, and a tilde range would still let a future 43.6.x land unverified. The repo already pins dugite exactly for the same reason.
  • --liftoff-only on the server spawn was rejected as a shipped fix: it is a performance cost on every PHP request and hides a V8 bug rather than avoiding it. It is recorded here because it is a useful diagnostic and a fallback if a future Electron cannot be pinned.
Review outcome (required — see AGENTS.md)

3 [fix here] · 1 [follow-up] — 2 fixed, 1 downgraded to follow-up with the reviewer's own criterion, 1 follow-up recorded.

  • Review: completed — fresh-context review agent (separate from the session that produced the change), against .github/instructions/code-review.instructions.md; reviewed head 78d1e98 / base 9d2bc17 (trunk); outcome: 4 findings.
    • 🟡 Tests, [fix here]: no automated test for the regression. The reviewer set the condition: if a bare php.wasm boot does not trip the crash on 43.7.x, the placement is the opt-in real-setup lane plus a TESTING.md note, and it drops to [follow-up]. Verified: a bare run, light and heavy, passes on 43.7.0; only the full server boot crashes, and an empty docroot errors instead. TESTING.md note added in the second commit; the automatic trigger is the follow-up under Risks.
    • 🔵 Architecture, [fix here]: the ceiling existed only in the commit message. Fixed: AGENTS.md architecture note in the second commit.
    • 🔵 Cross-platform, [fix here]: tests/unit/electron-node-version.test.cjs header still named 43.2.0's Node. Fixed in the second commit.
    • 🟡 Security, [follow-up]: the 43.7.x backports given up, and the Trac window as the one remote-content surface. Recorded under Risks; no reachable fix among them.
  • Since review: 78d1e98 → 3a9743d checked; the second commit is documentation and one comment line. Lint and both unit runs were rerun on 3a9743d.
  • CodeRabbit: not run. Requested at 15:03Z; it answered "Review limit reached, next included review available in 12 minutes" (run 1dd6843a-808d-4839-8aa5-2a175e5ebaf8, rate limited). Re-requested once at 15:16Z after the wait, but the PR had been merged at 15:14Z, so it answered "Pull request is closed". The check reads pass but no review happened. The fresh-context review above, on 78d1e98 with the 3a9743d delta checked, is the review of record.
  • CI on 3a9743d: eslint, unit (macOS, Windows), journeys (macOS, Windows) and packaged smoke (macOS, Windows) all passed before merge.
Implementation notes
  • The bisect ran each Electron's Electron Helper binary with ELECTRON_RUN_AS_NODE=1, which is what nodeExecPath() resolves to on macOS, against a real site's build/ through src/server-runner.js, killing the child once it printed SERVER_URL:.
  • Crash report excerpt (binary is stripped, symbols are nearest-match): Thread 8 Crashed:: V8Worker, KERN_PROTECTION_FAILURE at 0x0000010847fdffd8, faulting inside a 128 MB ---/rwx region.
  • Deterministic layer on the head: npm run lint clean; npm test 1674 pass, 2 skipped; npm run test:electron 1676 pass; npm run test:e2e 33 passed; the server runner on the installed Helper started 5/5.
Screenshots or recording

Nothing on screen changes. The visible difference is that Start dev server works again on Apple Silicon.

🤖 Generated with Claude Code

zaerl and others added 2 commits September 28, 2026 16:53
…ut crashing

Since #537 moved electron to 43.7.5, "Start dev server" dies on Apple Silicon macOS within about a second: the Playground server child exits with SIGBUS, a KERN_PROTECTION_FAILURE on a V8Worker thread. Running src/server-runner.js directly on each Electron Helper as Node bisects it to 43.7.0: 43.2.0 through 43.6.0 start the server 5/5, 43.7.0 and 43.7.5 crash 5/5. Plain Node 24.21.0, the Node that 43.7.0 bumped to, runs it fine, and both Playground CLI 3.1.47 and 3.1.56 behave the same, so the cause is in the V8 backports 43.7.0 carries. The crash disappears under --liftoff-only and persists under --no-liftoff, --single-threaded and --no-wasm-dynamic-tiering, which places it in V8's optimizing WebAssembly compiler.

The pin is exact rather than a caret range so a future npm update cannot walk back onto 43.7.x. The allowScripts key follows the version.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ev server

AGENTS.md records the 43.6.0 pin, the symptom above it and the bisect, so the next bumper does not find an unexplained exact version with a newer one on npm and a green CI. TESTING.md says that the real-setup workflow is the only test that starts the Playground server on Electron's bundled Node, and that an Electron bump needs it or a manual start on Apple Silicon. The electron-node-version header named the Node that 43.2.0 bundled; 43.6.0 bundles 24.20.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 12 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 1dd6843a-808d-4839-8aa5-2a175e5ebaf8

📥 Commits

Reviewing files that changed from the base of the PR and between 9d2bc17 and 3a9743d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !package-lock.json
📒 Files selected for processing (4)
  • AGENTS.md
  • TESTING.md
  • package.json
  • tests/unit/electron-node-version.test.cjs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@zaerl

zaerl commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@zaerl
zaerl merged commit b0021e3 into trunk Sep 28, 2026
8 checks passed
@zaerl
zaerl deleted the fix/pin-electron-43-6 branch September 28, 2026 15:14
@zaerl

zaerl commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ryanwelcher ryanwelcher mentioned this pull request Oct 1, 2026
@zaerl zaerl added this to the v2.0.0 milestone Oct 7, 2026
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.

1 participant