Acknowledgements
Minimal reproduction URL
https://github.com/rexxars/tsx-tsimport-hang
Problem & expected behavior (under 200 words)
Regression in 4.22.0 (4.21.0 works). On Node versions where tsx uses async module.register() (below 24.11.1 / 25.1.0: all of Node 18/20/22/23 and most 24.x), tsImport() of a module containing a failing relative import stops settling once enough registrations accumulate: calls 1-5 reject with ERR_MODULE_NOT_FOUND as expected, the 6th call never settles and the process hangs forever, idle. Any failing relative import from a TypeScript file triggers it; an unloadable extension like .svg hangs the same way with ERR_UNKNOWN_FILE_EXTENSION.
Expected: all calls reject and the script completes, as on 4.21.0 and on Node >= 24.11.1 (the registerHooks path).
Cause (debugged): since 4.22.0, src/esm/api/register.ts imports the hook factories, so bundling moved the hook module, including the mutable data singleton (namespace, active flag), into a shared chunk. The cache-busted ./esm/index.mjs?<timestamp> entry re-evaluates per registration, but the shared chunk evaluates once, so every initialize() overwrites the same state. All chained registrations then claim the latest namespace, and each re-applies TypeScript extension guessing to the failed candidates of the hook above it, multiplying resolution work roughly 10x per registration. unregister() doesn't help since active is shared too.
Bugs are expected to be fixed by those affected by it
Compensating engineering work will speed up resolution and support the project
Acknowledgements
Minimal reproduction URL
https://github.com/rexxars/tsx-tsimport-hang
Problem & expected behavior (under 200 words)
Regression in 4.22.0 (4.21.0 works). On Node versions where tsx uses async
module.register()(below 24.11.1 / 25.1.0: all of Node 18/20/22/23 and most 24.x),tsImport()of a module containing a failing relative import stops settling once enough registrations accumulate: calls 1-5 reject withERR_MODULE_NOT_FOUNDas expected, the 6th call never settles and the process hangs forever, idle. Any failing relative import from a TypeScript file triggers it; an unloadable extension like .svg hangs the same way withERR_UNKNOWN_FILE_EXTENSION.Expected: all calls reject and the script completes, as on 4.21.0 and on Node >= 24.11.1 (the
registerHookspath).Cause (debugged): since 4.22.0,
src/esm/api/register.tsimports the hook factories, so bundling moved the hook module, including the mutable data singleton (namespace, active flag), into a shared chunk. The cache-busted./esm/index.mjs?<timestamp>entry re-evaluates per registration, but the shared chunk evaluates once, so everyinitialize()overwrites the same state. All chained registrations then claim the latest namespace, and each re-applies TypeScript extension guessing to the failed candidates of the hook above it, multiplying resolution work roughly 10x per registration.unregister()doesn't help since active is shared too.Bugs are expected to be fixed by those affected by it
Compensating engineering work will speed up resolution and support the project