You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ethers fails at link: undefined references from a re-export-from-builtin shape (export { createHash, ... } from "crypto"), now reachable after #10757 #10802
With the HIR-lowering blowup fixed (#10757 / PR #10801), ethers 6.17.0's full 153-module dependency tree now lowers and generates code in about a minute. It then fails at the link step on undefined references.
Found immediately after #10757's fix, on origin/main + PR #10801, Linux x64.
The shape
The undefined symbols come from ethers/src.ts/crypto/crypto.ts, which re-exports node builtins:
So this is an export { … } from "<node builtin>" pass-through — the module re-exports names it never imports into its own scope — and those symbols are not emitted or resolved at link time.
Why it is filed separately
It is unrelated to #10757: that was an exponential blowup in class_mutates_capture's recursion, entirely within HIR lowering. This is a linker-visible symbol-emission problem that only became reachable because lowering now completes. The #10757 fix is correct and complete for what it claims; this is the next thing in the way.
That is also the expected pattern for this campaign — each blocker removed exposes the next. It is the removals doing their job, not evidence the previous fix was wrong.
Reproduction
mkdir ethers-probe &&cd ethers-probe
npm install ethers@6.17.0
# package.json: { "perry": { "compilePackages": ["ethers"] } }# fixture.ts: import { Wallet } from "ethers"; ...
perry compile fixture.ts -o fixture # lowers + codegens, then fails at link
Suggested first check
Whether a minimal export { createHash } from "crypto"; inside a compiled package reproduces it without ethers. If it does, the defect is in the re-export-from-builtin path generally, and is likely to affect any package wrapping node crypto — a common shape in anything that hashes or signs.
This is almost certainly #10432, which already has a six-line reproducer — so this does not need ethers checked out to work on.
#10432 ("Re-exporting a Node builtin's named export through a local module is broken", open, found 2026-09-06 on v0.5.1587, Linux x64) reports exactly the shape ethers hits:
the export { x } from "<builtin>" form produces an undefined perry_fn_<module>__<x> symbol at link time, and the import { x } from "<builtin>"; export { x } form links but the imported value returns undefined when called.
ethers/src.ts/crypto/crypto.ts is export { createHash, createHmac, pbkdf2Sync, randomBytes } from "crypto" — the first form — and the undefined symbols here are perry_fn_..._crypto_ts__createHmac / pbkdf2Sync / randomBytes / createHash. Same form, same symbol shape, same builtin.
Its case 1 is:
echo'export { createHash } from "crypto";'> dep.ts
# main.ts imports createHash from ./dep.ts
That is a much better starting point than a 153-module dependency tree, and it also records the second form's distinct failure — links fine, returns undefined at call time — which this issue would not have surfaced on its own, because ethers never gets past the link.
Worth cross-linking rather than merging outright, since this issue carries something #10432 does not: the real-world blast radius, and the WebSocket wrapper symbol, which may or may not be the same root cause. If it turns out to be, closing this as a duplicate of #10432 and carrying the ethers acceptance case over there is probably the right end state.
Context on the other half: #10801 (the class_mutates_capture memoization) is queued for a merge train and should land shortly, at which point ethers lowers and codegens — 153 modules, 0 JS fallback, about a minute — and this link failure becomes the only thing between that and a working build. So this is now the single blocker for ethers, not one of two.
#10757 should not be closed on #10801 alone. "Compiles" is not "links", and closing it would lose the thread from the original never-finishes report to this.
Fixed in v0.5.1632 (merge train 252, 841b605c97) by #10867 — fix(modules): preserve named Node builtin re-exports. Regression test crates/perry-hir/tests/node_named_export_hygiene.rs.
Train validation: 173 gap fixtures across seven areas with zero regressions, re-run against the current base after v0.5.1631 changed canonical_dir's path resolution. All ratchets, cargo fmt, and cargo check --workspace --all-targets under -D warnings clean.
Activity
proggeramlug commentedon Sep 20, 2026
This is almost certainly #10432, which already has a six-line reproducer — so this does not need ethers checked out to work on.
#10432 ("Re-exporting a Node builtin's named export through a local module is broken", open, found 2026-09-06 on v0.5.1587, Linux x64) reports exactly the shape ethers hits:
ethers/src.ts/crypto/crypto.tsisexport { createHash, createHmac, pbkdf2Sync, randomBytes } from "crypto"— the first form — and the undefined symbols here areperry_fn_..._crypto_ts__createHmac/pbkdf2Sync/randomBytes/createHash. Same form, same symbol shape, same builtin.Its case 1 is:
That is a much better starting point than a 153-module dependency tree, and it also records the second form's distinct failure — links fine, returns
undefinedat call time — which this issue would not have surfaced on its own, because ethers never gets past the link.Worth cross-linking rather than merging outright, since this issue carries something #10432 does not: the real-world blast radius, and the WebSocket wrapper symbol, which may or may not be the same root cause. If it turns out to be, closing this as a duplicate of #10432 and carrying the ethers acceptance case over there is probably the right end state.
Context on the other half: #10801 (the
class_mutates_capturememoization) is queued for a merge train and should land shortly, at which point ethers lowers and codegens — 153 modules, 0 JS fallback, about a minute — and this link failure becomes the only thing between that and a working build. So this is now the single blocker for ethers, not one of two.#10757 should not be closed on #10801 alone. "Compiles" is not "links", and closing it would lose the thread from the original never-finishes report to this.
proggeramlug commentedon Sep 21, 2026
Fixed in v0.5.1632 (merge train 252,
841b605c97) by #10867 —fix(modules): preserve named Node builtin re-exports. Regression testcrates/perry-hir/tests/node_named_export_hygiene.rs.Train validation: 173 gap fixtures across seven areas with zero regressions, re-run against the current base after v0.5.1631 changed
canonical_dir's path resolution. All ratchets,cargo fmt, andcargo check --workspace --all-targetsunder-D warningsclean.fix(modules): synthesize native-import re-exports for non-core npm pa…
fix(modules): synthesize native-import re-exports for non-core npm pa…