Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No such built-in module commming from import-in-the-middle when using ts-node #12480

Closed
3 tasks done
Tracked by #12485
AnthonyDugarte opened this issue Jun 12, 2024 · 8 comments
Closed
3 tasks done
Tracked by #12485
Assignees
Labels

Comments

@AnthonyDugarte
Copy link

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/node

SDK Version

8.9.1

Framework Version

Node v20.12.1

Link to Sentry event

No response

SDK Setup

Sentry.init({
    dsn,
    environment,
    enabled,
    tracesSampleRate,
});

Steps to Reproduce

Migrated from v7 to v8.

Added the @sentry/node/preload and it failed to run.

#12357 is similar but it's using tsx, the loaders order is wrong according to the thread; here I'm explicitly specifing the loaders order and I'm using ts-node with EMS. Using tsx is not negotiable given that they don't support the experimental legacy decorators.

By following #12422, I was able to make it work using: tsc --build && node --import @sentry/node/preload -r dotenv/config dist/index.js; but that's by not using ts-node, which is the issue I'm bringing up.

Expected Result

No error

Actual Result

SENTRY_DEBUG=1 node --import @sentry/node/preload --import ../ts-node.register.mjs -r dotenv/config src/index.ts
Sentry Logger [debug]: @opentelemetry/api: Registered a global for diag v1.9.0.
Sentry Logger [log]: [Sentry] Preloaded Http instrumentation
Sentry Logger [log]: [Sentry] Preloaded Express instrumentation
Sentry Logger [log]: [Sentry] Preloaded Connect instrumentation
Sentry Logger [log]: [Sentry] Preloaded Fastify instrumentation
Sentry Logger [log]: [Sentry] Preloaded Hapi instrumentation
Sentry Logger [log]: [Sentry] Preloaded Koa instrumentation
Sentry Logger [log]: [Sentry] Preloaded Nest instrumentation
Sentry Logger [log]: [Sentry] Preloaded Mongo instrumentation
Sentry Logger [log]: [Sentry] Preloaded Mongoose instrumentation
Sentry Logger [log]: [Sentry] Preloaded Mysql instrumentation
Sentry Logger [log]: [Sentry] Preloaded Mysql2 instrumentation
Sentry Logger [log]: [Sentry] Preloaded Postgres instrumentation
Sentry Logger [log]: [Sentry] Preloaded Hapi instrumentation
Sentry Logger [log]: [Sentry] Preloaded Graphql instrumentation
Sentry Logger [log]: [Sentry] Preloaded Redis instrumentation
Error [ERR_UNKNOWN_BUILTIN_MODULE]: No such built-in module: node:http?iitm=true
    at ModuleLoader.builtinStrategy (node:internal/modules/esm/translators:465:11)
    at callTranslator (node:internal/modules/esm/loader:279:14)
    at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:30) {
  code: 'ERR_UNKNOWN_BUILTIN_MODULE'
}

../ts-node.register.mjs content is:

import { register } from "node:module";
import { pathToFileURL } from "node:url";

process.on('uncaughtException', function (err) {
  console.error(err);
  process.exit(1);
});

register("ts-node/esm", pathToFileURL("./"));
@github-actions github-actions bot added the Package: node Issues related to the Sentry Node SDK label Jun 12, 2024
@AbhiPrasad AbhiPrasad added this to the v8 Instrumentation Issues milestone Jun 12, 2024
@Lms24
Copy link
Member

Lms24 commented Jun 13, 2024

Hi, thanks for reporting, we'll take a look!

@timfish
Copy link
Collaborator

timfish commented Jun 13, 2024

It's a shame the stack trace from Node is so short and unhelpful!

I can reproduce this but I can also work around it by reversing the order of the --import:

node --import ./ts-node.register.mjs --import @sentry/node/preload -r dotenv/config src/index.ts

This changes the order that the various ESM loader hooks are registered and therefore the order that they're called to resolve and load source code.

@AnthonyDugarte
Copy link
Author

AnthonyDugarte commented Jun 14, 2024

By switching the order I get a different error:

[Error: ENOENT: no such file or directory, open '/path-to-app/src/controllers/users.controller.js'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/path-to-app/src/controllers/users.controller.js'
}

src/index.ts has an import to the controllers folder index file that looks like:

import { UserController, ...otherControllers } from './controllers/index.js';

and src/controllers/index.ts content is simply:

export * from './users.controller.js';
// ... other controllers

It's worth noticing that by switching the src/controllers/index.ts content to use .ts import termination and enabling "allowImportingTsExtensions": true in the tsconfig.json, the error goes the a different .js file termination.

export * from './users.controller.ts';
// ... other controllers

I have a bunch of imports so didn't update them all to try if the app runs correctly, will try it and share an update.


Edit 1

It seems to be an issue with index.ts files that is filled only with export * expressions.

I updated all the: export * from './path-to-file.js' to be export * from './path-to-file.ts' in index.ts file, and the app booted up.


Edit 2

By updating the exports to be explicit, export { A, B, C } from './file.js' and reverting back to the .js export syntax the app ran correctly, it is an issue with the export * from './file.js' expression.

@AnthonyDugarte
Copy link
Author

AnthonyDugarte commented Jun 18, 2024

Any update on this?

The export * from './module.js' syntax keeps failing on @sentry/[email protected]

@AnthonyDugarte
Copy link
Author

Here's a repo on which the issue is reproduced.

https://github.com/AnthonyDugarte/sentry-node-export-all-issue

@AnthonyDugarte
Copy link
Author

Found a monkeypatch, at https://github.com/DataDog/import-in-the-middle/blob/88605a707a63af9797986aa6a100161fe02aace6/hook.js#L169:

- if (isBareSpecifier(modFile)) {
+ if (isBareSpecifier(modFile) || srcUrl.endsWith('.ts')) {

in order to generate the exports for a module that is star exporting (export * from './module.js), it needs to resolve the actual module.

But given that modFile is a relative path: const [, modFile] = n.split('* from '), modFile is set to './module.js'.

So the condition isBareSpecifier(modFile) fails, and it simply tries to resolve as if the file actually existed, but it does not given that we are processing a typescript file on the fly via ts-node:

      } else {
        modUrl = new URL(modFile, srcUrl).href
      }

the monkeypatch forces the tool to resolve relative paths to imports that are part of a typescript file (srcUrl.endsWith('.ts')).

@AnthonyDugarte
Copy link
Author

by applying this patches provided here the app runs with star exports.

@AbhiPrasad
Copy link
Member

With the newest release of import-in-the-middle v1.9.0 this should be fixed.

If you upgrade to a fresh install of the latest version of the Node SDK it should use [email protected] by default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

No branches or pull requests

5 participants