Skip to content

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

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.

Activity

  1. aduh95 commented on Sep 23, 2025

    @aduh95
    Contributor

    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 repro

    I'm getting Hello from file3.mts, indicating this has already been fixed; I'm getting ERR_INTERNAL_ASSERTION on the second case, so I can confirm this one should be fixed.

  2. added
    moduleIssues and PRs related to the module subsystem.
    strip-typesIssues and PRs related to TypeScript type stripping.
    on Sep 30, 2025
  3. added a commit that references this issue on Oct 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.moduleIssues and PRs related to the module subsystem.strip-typesIssues and PRs related to TypeScript type stripping.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions