Skip to content

Node throws error when require'ing ESM module in TypeScript in nested ESM/CJS context #59963

@sjoerdvanBommel

Description

@sjoerdvanBommel

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.moduleIssues and PRs related to the module subsystem.strip-typesIssues or PRs related to strip-types support

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions