Repository navigation
Node throws error when require'ing ESM module in TypeScript in nested ESM/CJS context #59963
Description
Version
v24.8.0
Platform
Darwin mac.home 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:53:27 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6041 arm64
Subsystem
No response
What steps will reproduce the bug?
Reproducing this requires 2 .mts and 1 .cts file:
file1.mts
import { message } from "./file2.cts";
console.log(message);
file2.cts
const { message } = require("./file3.mts");
module.exports = { message };
file3.mts
export const message = "Hello from file3.mts";
A similar error is reproducable with 2 .cts files and 1 .mts file:
file1.cts
const { message } = require("./file2.mts");
console.log(message);
file2.mts
export { message } from "./file3.cts";
file3.cts
const message = "Hello from file3.cts";
module.exports = { message };
Running node file1.mts (or node file1.cts) triggers the error.
How often does it reproduce? Is there a required condition?
Always, requires a node.js version that supports require'ing ESM module and running TS by stripping types
What is the expected behavior? Why is that the expected behavior?
I'd expect node to allow me to require ESM modules even in these "nested" cases. Exactly the same code works fine in pure JavaScript, this only errors when importing/requiring TypeScript files directly.
What do you see instead?
node:internal/assert:11
throw new ERR_INTERNAL_ASSERTION(message);
^
Error [ERR_INTERNAL_ASSERTION]: Imported CJS module file:///Users/sjoerdvanbommel/workspace/personal/lab/esm-cjs-esm/file2.cts failed to load module file:///Users/sjoerdvanbommel/workspace/personal/lab/esm-cjs-esm/file3.mts using require()
This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues
at assert (node:internal/assert:11:11)
at require (node:internal/modules/esm/translators:158:5)
at Object.<anonymous> (file:///Users/sjoerdvanbommel/workspace/personal/lab/esm-cjs-esm/file2.cts:1:21)
at loadCJSModule (node:internal/modules/esm/translators:178:3)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:221:7)
at ModuleJob.run (node:internal/modules/esm/module_job:371:25)
at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:702:26)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5) {
code: 'ERR_INTERNAL_ASSERTION'
}
Node.js v24.8.0
Additional information
This error only occurs in cases like ESM -> CJS -> ESM or CJS -> ESM -> CJS and when using TypeScript files directly. When there's only a single import/require from ESM -> CJS or CJS -> ESM, or when using JavaScript, it works as expected.
Activity
aduh95 commentedon Sep 23, 2025
Using the following repro script:
rm -rf repro ( set -e mkdir repro cd repro echo 'import { message } from "./file2.cts";console.log(message);' > file1.mts echo 'const { message } = require("./file3.mts");module.exports = { message };' > file2.cts echo 'export const message = "Hello from file3.mts";' > file3.mts node file1.mts || true echo 'const { message } = require("./file2.mts");console.log(message);' > file1.cts echo 'export { message } from "./file3.cts";' > file2.mts echo 'const message = "Hello from file3.cts";module.exports = { message };' > file3.cts node file1.cts || true ) || true rm -rf reproI'm getting
Hello from file3.mts, indicating this has already been fixed; I'm gettingERR_INTERNAL_ASSERTIONon the second case, so I can confirm this one should be fixed.module: use sync cjs when importing cts
module: use sync cjs when importing cts
module: use sync cjs when importing cts