Skip to content

require-in-the-middle is resolved to import-in-the-middle and crashing with turbopack #64022

@lforst

Description

@lforst

Link to the code that reproduces this issue

https://github.com/lforst/nextjs-turbo-in-the-middle-repro

To Reproduce

After checking out repo:

  1. npm i
  2. npm run dev:turbo (this will just run next dev --turbo)
  3. App crashes

Current vs. Expected behavior

Currently the app crashes. As soon as I run the app without the --turbo flag everything works as expected. (We get a few warnings but this is fine)

Provide environment information

Operating System:
  Platform: linux
  Arch: arm64
  Version: #15-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan  9 22:39:36 UTC 2024
  Available memory (MB): 15962
  Available CPU cores: 6
Binaries:
  Node: 18.18.2
  npm: 9.8.1
  Yarn: 1.22.22
  pnpm: 8.15.5
Relevant Packages:
  next: 14.2.0-canary.54 // Latest available version is detected (14.2.0-canary.54).
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A

Nextjs config has instrumentationHook enabled.

Which area(s) are affected? (Select all that apply)

Turbopack (--turbo)

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

Some digging I did

What is wrong? First of all the app crashes, while it likely shouldn't. Dev mode without turbopack runs fine.

The crash likely looks something like:

> dev:turbo
> next dev --turbo

  ▲ Next.js 14.2.0-canary.54 (turbo)
  - Local:        http://localhost:3000
  - Experiments (use with caution):
    · instrumentationHook

 ✓ Starting...
TypeError: An error occurred while loading instrumentation hook: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f40$opentelemetry$2f$instrumentation$2f$node_modules$2f$import$2d$in$2d$the$2d$middle$2f$index$2e$js__$5b$instrumentation$5d$__$28$ecmascript$29$__ is not a constructor
    at _loop_1 (/tmp/reproduction-app/.next/server/chunks/node_modules_606038._.js:5783:27)
    at InstrumentationBase.enable (/tmp/reproduction-app/.next/server/chunks/node_modules_606038._.js:5794:17)
    at new InstrumentationBase (/tmp/reproduction-app/.next/server/chunks/node_modules_606038._.js:5640:19)
    at new MyInstrumentation (/tmp/reproduction-app/.next/server/chunks/instrumentation_ts_ca8ae5._.js:21:9)
    at Module.register (/tmp/reproduction-app/.next/server/chunks/instrumentation_ts_ca8ae5._.js:16:31)
    at DevServer.runInstrumentationHookIfAvailable (/tmp/reproduction-app/node_modules/next/dist/server/dev/next-dev-server.js:437:43)
    at async Span.traceAsyncFn (/tmp/reproduction-app/node_modules/next/dist/trace/trace.js:154:20)
    at async DevServer.prepareImpl (/tmp/reproduction-app/node_modules/next/dist/server/dev/next-dev-server.js:214:9)
    at async NextServer.prepare (/tmp/reproduction-app/node_modules/next/dist/server/next.js:161:13)
    at async initializeImpl (/tmp/reproduction-app/node_modules/next/dist/server/lib/render-server.js:98:5)
    at async initialize (/tmp/reproduction-app/node_modules/next/dist/server/lib/router-server.js:423:22)
    at async Server.<anonymous> (/tmp/reproduction-app/node_modules/next/dist/server/lib/start-server.js:249:36)

If we take a look at the code of the top frame /tmp/reproduction-app/.next/server/chunks/node*modules_606038.*.js:5783:27 we end up at a location that looks as follows:

// `RequireInTheMiddleSingleton` does not support absolute paths.
// For an absolute paths, we must create a separate instance of the
// require-in-the-middle `Hook`.
var hook = __TURBOPACK__commonjs__external__path__.isAbsolute(module_2.name) ? new __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$require$2d$in$2d$the$2d$middle$2f$index$2e$js__$5b$instrumentation$5d$__$28$ecmascript$29$__["Hook"]([
    module_2.name
], {
    internals: true
}, onRequire) : this_1._requireInTheMiddleSingleton.register(module_2.name, onRequire);
this_1._hooks.push(hook);
var esmHook = new __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f40$opentelemetry$2f$instrumentation$2f$node_modules$2f$import$2d$in$2d$the$2d$middle$2f$index$2e$js__$5b$instrumentation$5d$__$28$ecmascript$29$__([
    module_2.name
], {
    internals: false
}, hookFn);
this_1._hooks.push(esmHook);

Searching for the comment on top code on github (https://github.com/search?type=code&q=%22%2F%2F+%60RequireInTheMiddleSingleton%60+does+not+support+absolute+paths.%22) lets us deduct that it comes from here: https://github.com/open-telemetry/opentelemetry-js/blob/e01f493a2480bda39f9ee67da1c33f31a57f91ff/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts#L262.

It seems like the new Hook() call fails because it is not a class. Weird.

If we look at the cryptic variable name __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f40$opentelemetry$2f$instrumentation$2f$node_modules$2f$import$2d$in$2d$the$2d$middle$2f$index$2e$js__$5b$instrumentation$5d$__$28$ecmascript$29$__ it looks like it is trying to import from import-in-the-middle, HOWEVER, the original source is importing Hook from require-in-the-middle: https://github.com/open-telemetry/opentelemetry-js/blob/e01f493a2480bda39f9ee67da1c33f31a57f91ff/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts#L32 (here's the packaged code https://unpkg.com/browse/@opentelemetry/instrumentation@0.48.0/build/esm/platform/node/instrumentation.js)

I couldn't find any place where Next.js or turbopack would change how require-in-the-middle is resolved so this is where I am stomped. As far as I am concerned none of the OTEL deps are doing anything fishy..

Scratch the above, it seems like the way import-in-the-middle is imported is very weird. It is interesting though that turbopack's behaviour is different than webpack.

PACK-2916

Metadata

Metadata

Assignees

No one assigned

    Labels

    TurbopackRelated to Turbopack with Next.js.bugIssue was opened via the bug report template.linear: turbopackConfirmed issue that is tracked by the Turbopack team.locked

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions