Skip to content

ESM loader compatibility: ReferenceError with parseEnvVarBoolean in experimental.js #10654

@kjosyulajsq

Description

@kjosyulajsq

Describe the bug

Unleash v7 has a JavaScript hoisting bug that prevents any ESM loader from working correctly. When using Node.js ESM loaders (such as --import, --loader, or custom ESM hooks), the application fails to start with a ReferenceError: Cannot access 'parseEnvVarBoolean' before initialization.

This affects integration with APM tools like DataDog's dd-trace, OpenTelemetry, and any other tooling that relies on ESM loaders for instrumentation.

The issue appears to be in /node_modules/unleash-server/dist/lib/types/experimental.js where parseEnvVarBoolean is being accessed before it's properly initialized in the ESM module loading context.

Steps to reproduce the bug

Minimal reproduction:

Create a new npm project:

mkdir unleash-esm-test && cd unleash-esm-test
npm init -y
npm install [email protected] [email protected]

Create a simple ESM test file (test-esm.mjs):

import { start } from 'unleash-server';

console.log('Starting Unleash with ESM...');
start({
  port: 4242,
  db: {
    host: 'localhost',
    port: 5432,
    database: 'unleash',
    username: 'unleash_user',
    password: 'password',
    ssl: false
  }
});

Run with DataDog's official ESM approach:
node --import dd-trace/register.js test-esm.mjs

Result:
The application crashes immediately with the hoisting error, before any database connection is attempted.

All affected ESM loader approaches (all fail):
-- import dd-trace/register.js (DataDog's recommended ESM approach)
-- loader dd-trace/loader-hook.mjs (DataDog's legacy ESM approach)
-- Custom ESM hook files using register() from node:module
-- OpenTelemetry ESM instrumentation

Expected behavior

Unleash should start normally when using ESM loaders, allowing proper instrumentation by APM tools. The ESM loader should be able to instrument Express and other modules before they are imported by Unleash.

Logs, error output, etc.

file:///tmp/unleash-esm-test/node_modules/unleash-server/dist/lib/types/experimental.js:7
    responseTimeWithAppNameKillSwitch: parseEnvVarBoolean(process.env.UNLEASH_RESPONSE_TIME_WITH_APP_NAME_KILL_SWITCH, false),
                                       ^

ReferenceError: Cannot access 'parseEnvVarBoolean' before initialization
    at file:///tmp/unleash-esm-test/node_modules/unleash-server/dist/lib/types/experimental.js:7:40
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:66:12)

Screenshots

No response

Additional context

Unleash version: 7.1.0 (npm package)
Node.js version: 22
Operating System: macOS (also reproduced on Linux)
Package manager: npm
dd-trace version: 5.45.0

This may be related to the migration from CommonJS to ESM in v7.x. The issue doesn't occur with CommonJS initialization methods or when running Unleash v6.x.

Unleash version

7.1.0

Subscription type

Open source

Hosting type

Self-hosted

SDK information (language and version)

No response

Metadata

Metadata

Labels

Type

No type

Projects

Status

Investigating

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions