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
Improve the error message for missing modules #38892
Comments
cc @nodejs/modules |
What's the content of |
I think the issue is more about having a link with line/column number printed than anything. Showing the exact line of what the import looks like is a nicety though. |
Yes exactly. The problem is the user friendliness of the error. Rust error is really friendly, while ours is not. The one for CJS is not friendly either:
However this at least shows the actual line where the problem happens. |
node has a ton of places where eliding the stack frames for "node internals" would make things friendlier; I'm not sure why node doesn't try to do that. ftr having a line or line/column is great and i'm all for it, i'm just skeptical that it makes a difference in practice in this case. |
Can we change what's printed before the stack trace? What I personally find useless/confusing is this part:
|
I'd love if we could instead have something like:
|
I spent some time poking around the codebase and the line is actually in the stack, but the internals are polluting it with noise in a couple ways
$ cat a.mjs
import('e404.mjs');
$ NODE_OPTIONS='--stack-trace-limit=100' node ./a.mjs
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'e404.mjs' imported from /Users/bfarias/Documents/oss/node/a.mjs
at new NodeError (node:internal/errors:363:5)
at packageResolve (node:internal/modules/esm/resolve:698:9)
at moduleResolve (node:internal/modules/esm/resolve:739:18)
at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
at Loader.resolve (node:internal/modules/esm/loader:89:40)
at Loader.getModuleJob (node:internal/modules/esm/loader:242:28)
at Loader.import (node:internal/modules/esm/loader:177:28)
at importModuleDynamically (node:internal/modules/esm/translators:116:35)
at exports.importModuleDynamicallyCallback (node:internal/process/esm_loader:30:14)
at file:///Users/bfarias/Documents/oss/node/a.mjs:2:1
at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5) {
code: 'ERR_MODULE_NOT_FOUND'
} We could temporarily bump the limit while we are in core to be sure it is captured. There doesn't appear to be an API to bump the limit around a stack trace dynamically though.
node/lib/internal/process/promises.js Lines 225 to 227 in 09c9e5d
node/lib/internal/process/promises.js Lines 244 to 246 in 09c9e5d
These actually are adding a confusing stack frame even if we replace the stack using the V8 stack trace API. Doing so also is unreliable due to parts of Node adding a Likely this section of the codebase needs to just skip internals for the Honestly, I think hiding the internal errors by default is the best approach for not only this error, but others. Perhaps coalescing them under a We could likely add a lint rule to avoid direct assignment to |
I totally agree; I can't see any use case for showing stack frames from internals for the vast majority of node users (for any error anywhere, not just module errors) |
I played around with this a bit in Node v16.1.0. It seems the information is there, but it's not in the error object itself. To wit: Let's assume // foo.mjs
await import('./bar.mjs') Then I get: $ node foo.mjs
file:///Users/giltayar/code/tmp/try-stack/bar.mjs:4
askdjfhaksdf sadfhask fjhasdf
^^^^^^^^
SyntaxError: Unexpected identifier
at Loader.moduleStrategy (node:internal/modules/esm/translators:147:18)
at async link (node:internal/modules/esm/module_job:64:21) Full information needed to figure out the syntax error! Great. Yet if I try and catch the error and log it, as in: // foo.mjs
await import('./bar.mjs').catch(console.error) Then I get: $ node foo.mjs
SyntaxError: Unexpected identifier
at Loader.moduleStrategy (node:internal/modules/esm/translators:147:18)
at async link (node:internal/modules/esm/module_job:64:21) The information about the syntax error is gone! So when Node catches an exception, it finds the full information about the syntax error somewhere. So it's there, and it's just not stored in the |
Node has access to an internal method that can add this line. import internalUtil from 'internal/util';
await import('./bar.mjs').catch((err) => {
internalUtil.decorateErrorStack(err)
console.error(err)
})
|
@targos Nice! I was about to run and create a PR for Mocha, and then I saw the |
Currently, the error that is produced in case of a missing module is not really user friendly:
Rust for example provide more user friendly errors:
Note that our errors do not list which line the dependency was not specified.
What do you think? I think it would improve things long term.
The text was updated successfully, but these errors were encountered: