Skip to content

require(esm) inside a module.register() hook module fails with ERR_INTERNAL_ASSERTION in 26.12.0 #66767

Open

Description

@ivan-tymoshenko

Version

v26.12.0 (works on v26.11.1 and v26.10.0)

Platform

Linux x64

Subsystem

esm, module

What steps will reproduce the bug?

// repro.mjs
import { mkdtempSync, writeFileSync } from 'node:fs'
import { register } from 'node:module'
import { tmpdir } from 'node:os'
import { join } from 'node:path'

// Any ES module with at least one import (one without imports works)
const esm = join(mkdtempSync(join(tmpdir(), 'require-esm-')), 'esm.mjs')
writeFileSync(esm, "import 'node:fs'\n")

// The hook module defines no hooks: loading it in the hooks thread is enough
const hooks = `
import { createRequire } from 'node:module'
createRequire(${JSON.stringify(esm)})(${JSON.stringify(esm)})
`

register('data:text/javascript,' + encodeURIComponent(hooks))
console.log('ok')
node repro.mjs

How often does it reproduce? Is there a required condition?

Always. Required conditions:

  • The require() happens while loading a module.register() hook module (the hooks thread).
  • The required ES module has at least one import. With export {} instead, it prints ok.

No hooks need to be exported: the hook module defines none.

What is the expected behavior? Why is that the expected behavior?

ok is printed, as on v26.11.1 and v26.10.0 (which only print the module.register()
deprecation warning).

What do you see instead?

Error [ERR_INTERNAL_ASSERTION]: 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 ModuleJobSync.syncLink (node:internal/modules/esm/module_job:330:9)
    at ModuleJobSync.link (node:internal/modules/esm/module_job:626:17)
    at new ModuleJobSync (node:internal/modules/esm/module_job:616:26)
    at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:352:11)
    at loadESMFromCJS (node:internal/modules/cjs/loader:1786:24)
    at Module._compile (node:internal/modules/cjs/loader:1950:5)
    at Object..js (node:internal/modules/cjs/loader:2108:10)
    at Module.load (node:internal/modules/cjs/loader:1690:32)
    at Module._load (node:internal/modules/cjs/loader:1480:12) {
  code: 'ERR_INTERNAL_ASSERTION'
}

The failing assertion is assert(!isPromise(job)) in ModuleJobSync.syncLink(): inside the
hooks thread, getOrCreateModuleJob() returns a promise for the required module's dependency
while the module is being linked synchronously for require().

Additional information

Bisected between releases only: v26.11.1 works, v26.12.0 fails. v26.12.0 includes
"module: synchronously load most ES modules" (#62530), which changed this code path; that PR is
the likely cause but the exact commit was not bisected.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions