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

import throws ENOENT instead of ERR_MODULE_NOT_FOUND when a module is not found #100

Open
sgravrock opened this issue Jul 15, 2023 · 1 comment

Comments

@sgravrock
Copy link

sgravrock commented Jul 15, 2023

Normally, Node throws an error with code ERR_MODULE_NOT_FOUND when the requested module is not found. But when the testdouble ESM loader is used, an error with code ENOENT is thrown instead:

$ cat package.json 
{
  "devDependencies": {
    "testdouble": "^3.18.0"
  }
}
$ cat test.mjs 
import './nosuch.mjs';
$ node test.mjs 
node:internal/errors:465
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '[...]/nosuch.mjs' imported from [...]/test.mjs
    at new NodeError (node:internal/errors:372:5)
    at finalizeResolution (node:internal/modules/esm/resolve:405:11)
    at moduleResolve (node:internal/modules/esm/resolve:966:10)
    at defaultResolve (node:internal/modules/esm/resolve:1176:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v18.0.0
$ node --loader=testdouble test.mjs                   
(node:17583) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/process/esm_loader:91
    internalBinding('errors').triggerUncaughtException(
                              ^

[Error: ENOENT: no such file or directory, open [...]/nosuch.mjs'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '[...]/nosuch.mjs'
}


Node.js v18.0.0

I ran into this when documenting ways to mock ES modules with Jasmine. Jasmine tries to distinguish between a configuration file not existing and other types of errors loading a config file by checking the error code. The testdouble loader breaks that check, and that combined with another bug (jasmine tries to load jasmine.js even if jasmine.json is present) means that Jasmine doesn't work with the Testdouble loader if the default jasmine.json config file is used. I have a workaround that will ship in Jasmine 5.1.0, but the same problem could come up with other tools.

I'm not sure if this is fixable or not. My guess is that Node expects that a loader's resolve method will only return URLs referring to files that exist, but that approach seems like it could cause problems when multiple loaders are chained together.

(edited to fix some confusing copypasta)

@searls
Copy link
Member

searls commented Jul 17, 2023

This is a great issue. I unfortunately don't know the answer because I'm not familiar with the ESM side of quibble. @giltayar may know if it's possible to detect this is the cause and fire our own exception that looks like the real one

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

No branches or pull requests

2 participants