Repository navigation
hooks: in-thread ESM hooks from Node.js 22.22.3, 24.11.1 and 25.1 (nodejs/node#59929) - #53
Merged
Merged
Conversation
toabctl
force-pushed
the
wt-node-sync-hooks
branch
4 times, most recently
from
October 14, 2026 00:59
8828cd1 to
b7ba289
Compare
…dejs/node#59929) The in-thread hooks (module.registerHooks) were used only from Node.js 24.12 / 25.2, for a crash attributed to nodejs/node#60380: "registerHooks next to a loader-thread hook crashes". Spikes show the crash ("this[#customizations] .loadSync is not a function") comes from a --require preload calling registerHooks inside Node's own loader thread, which Node 22 - 24.11 run preloads in too; register.cjs does nothing there, so our hooks never trigger it. What does break in-thread hooks next to another loader is a loader-thread hook that returns no source for a CommonJS module (Node reads the file): rejected with ERR_INVALID_RETURN_PROPERTY_VALUE before nodejs/node#59929 - Node 22.22.3, 24.11.1, 25.1 (the versions import-in-the-middle and dd-trace check). Forced sync mode with OpenTelemetry's hook.mjs, dd-trace and Yarn Plug'n'Play: all builds right on 22.22.3, 22.23.2, 24.11.1; every one with another loader fails on 22.22.2 and 24.10.0. So the in-thread hooks are used from those versions on, in every process: current Node.js 22 no longer needs the loader thread (its cost, and the bundler-process gate that misses pnpm's and bun's isolated layouts). - syncHooksSafe, and the test matrix's SYNC_HOOKS, by those versions; unit test of the version table (22.22.2, 24.10.0, 24.11.0, 25.0: loader thread) - CI: the Node 22 matrix job also on 22.22.2 (nodejs-22~22.22.2), the last 22 with the loader-thread hooks, which older Node.js uses - the message when module.register fails names what breaks Node's loader thread (another tool's loader or a preload that calls module.registerHooks) instead of blaming bundle-lockfile - unit tests: the real entry module sees its file through import.meta (the ?bundle-lockfile-real URL); a cycle back into a wrapped entry reads the wrapper (TDZ during evaluation, the wrapped function later), documented in internals.md - test/node-versions.json: 22.22.2 / 24.10.0 the last with loader-thread hooks, 22.22.3 / 24.11.1 (pr) the first with in-thread ones; the safety net's messages and docs name the new versions - docs: README, bundlers.md, internals.md, troubleshooting.md: the versions; internals.md: the real causes Verified on the workstation: the full matrix on Wolfi's Node 22 (22.23.2, now in-thread), the Node 22 subset on 22.22.2 (loader thread), 22.22.3 and 24.11.1, unit tests on 20, 22.22.2, 22.22.3, 22.23.2, 24.10.0, 24.11.1, 24, 26. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
toabctl
force-pushed
the
wt-node-sync-hooks
branch
from
October 14, 2026 01:31
b7ba289 to
ec22074
Compare
toabctl
added a commit
that referenced
this pull request
Oct 14, 2026
CI failed twice tonight in fixture generation, before any test ran: yarn install got ECONNRESET from the registry (main at dc21e2f, PR #53, both wp5-yarn4-pnpm). gen.cjs now runs an install again, up to 3 times with a short pause, when its output names a network error (ECONNRESET, ETIMEDOUT, EAI_AGAIN, ECONNREFUSED, EPIPE, socket hang up); any other failure fails at once, as before. Only fixture creation retries; no assertion changes. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The in-thread ESM hooks (
module.registerHooks) were only used from Node.js 24.12 / 25.2, for a crash we had attributed to nodejs/node#60380. Plan 03's spikes found the real causes:this[#customizations].loadSync is not a function): a--requirepreload callingregisterHooksinside Node's own loader thread, which Node 22 – 24.11 runs preloads in too.register.cjsreturns there, so our hooks never trigger it.hook.mjs): a loader-thread hook that returns no source for a CommonJS module is rejected withERR_INVALID_RETURN_PROPERTY_VALUEbefore module: handle null source from async loader hooks in sync hooks nodejs/node#59929, i.e. before Node 22.22.3, 24.11.1 and 25.1 — the same gate import-in-the-middle and dd-trace use. Verified: forced sync with OTel, dd-trace and PnP gives the right lockfiles on 22.22.3, 22.23.2 and 24.11.1, and fails on 22.22.2 and 24.10.0.So from those versions on, the in-thread hooks are used in every process. Current Node 22 no longer needs the loader thread, which removes its cost and the bundler-process gate, the gate that misses pnpm/bun isolated layouts (plan 02 S1).
Changes
syncHooksSafeand the matrix'sSYNC_HOOKSuse those versions. A unit-tested version table covers 22.22.2, 24.10.0, 24.11.0 and 25.0, which stay on the loader thread.nodejs-22=22.22.2-r1), the last 22 with the loader-thread hooks that older Node.js uses. Latest 22 now covers the in-thread path.module.registerfails, the error names what breaks Node's loader thread (another tool's loader, or a preload that callsregisterHooks) instead of blaming bundle-lockfile.import.meta, despite the?bundle-lockfile-realURL;require(): 22.22.2 warns there, with and without bundle-lockfile.Verified on the workstation (Wolfi containers)
🤖 Generated with Claude Code