Loading @platformatic/kafka via IITM crashes with ReferenceError

Open
#290 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
javascript, node.js

Research direction

Start by running the provided app.mjs and register.mjs reproduction with Node.js, then compare native loading with the IITM-wrapped module graph. Inspect dist/index.js, registries/index.js, confluent-schema-registry.js, and errors.js to trace the UserError cycle and evaluation order. Done means the cause and whether IITM can preserve the expected loading behavior are established, with a focused regression test if appropriate.

Written by the indexing model from the issue text.

Description

Description

Loading @platformatic/kafka through import-in-the-middle causes the application to crash with a ReferenceError, while the same application works correctly without IITM.

Reproduction

app.mjs

import { Producer } from '@platformatic/kafka';

console.log('Loaded successfully. Producer:', Producer.name);

register.mjs

import { register } from 'node:module';
import { addHook } from 'import-in-the-middle';

register('import-in-the-middle/hook.mjs', import.meta.url);

addHook((name, exports) => {
  // No-op — just having IITM active is enough to trigger the crash.
  return exports;
});

Run with:

node --import ./register.mjs app.mjs
Expected
Loaded successfully. Producer: Producer
Actual

The application crashes with:

ReferenceError: Cannot access 'UserError' before initialization
    at .../node_modules/@platformatic/kafka/dist/registries/confluent-schema-registry.js:50:44
Root cause / observations

@platformatic/kafka appears to have a circular ESM dependency through its own barrel (dist/index.js):

dist/index.js
  └── re-exports registries/index.js
        └── re-exports confluent-schema-registry.js
              └── imports { UserError } from "../index.js"
                    └── back to dist/index.js

dist/index.js also re-exports errors.js, where UserError is defined:

export class UserError extends GenericError { … }

Without IITM, Node's native ESM evaluation order allows UserError to be initialized before it is accessed by confluent-schema-registry.js.

However, when IITM wraps the module graph, it appears to alter the module evaluation order such that confluent-schema-registry.js is evaluated before the UserError binding has been initialized.

The access to the live ESM binding therefore occurs while it is still in the Temporal Dead Zone, resulting in:

ReferenceError: Cannot access 'UserError' before initialization
Notes

The circular dependency itself appears to be an issue in @platformatic/kafka, and importing UserError directly from errors.js instead of through the package barrel would likely remove the cycle.

However, the same package loads successfully with native Node ESM and only fails when the module graph is processed through IITM.

It would be helpful to understand whether IITM can preserve the native ESM evaluation semantics in this scenario, or whether there is a recommended way to handle circular ESM dependencies when modules are wrapped by IITM.

Environment
  • Node.js: v24.18.0
  • import-in-the-middle: 3.4.0
  • @platformatic/kafka: 2.11.0
  • OS: macOS
Dominant language
JavaScript
Stars
170
Forks
58
Avg merge
3d 19h
Merged PRs (30d)
7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from nodejs/import-in-the-middle

All issues in nodejs/import-in-the-middle

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.