Skip to content

lib: improve error message on missing module

The error message we provide when a module is missing is not very useful, specially for new users. Consider:

$ node index.js
internal/modules/cjs/loader.js:605
    throw err;
    ^

Error: Cannot find module 'this-module-does-not-exist'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:603:15)
    at Function.Module._load (internal/modules/cjs/loader.js:529:25)
    at Module.require (internal/modules/cjs/loader.js:657:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/Users/ofrobots/tmp/require-error/who-loaded-dis.js:1:63)
    at Module._compile (internal/modules/cjs/loader.js:721:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
    at Function.Module._load (internal/modules/cjs/loader.js:552:3)

This has a lot internal details and very little useful information for the user. The key information relevant to the user in the above is the line at Object.<anonymous> (/Users/ofrobots/tmp/require-error/who-loaded-dis.js:1:63). It is less than obvious that this is what the user should pay attention to. In deeply nested dependencies it may not be clear to the user where this require itself came from. Users have to start grepping their node_modules at this point.

This PR proposes to change this to something like:

$ node index.js
internal/modules/cjs/loader.js:625
    throw err;
    ^

Error: Cannot find module 'this-module-does-not-exist'
Require stack:
- /Users/ofrobots/tmp/require-error/who-loaded-dis.js
- /Users/ofrobots/tmp/require-error/deeply-nested-module.js
- /Users/ofrobots/tmp/require-error/direct-dependency.js
- /Users/ofrobots/tmp/require-error/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:622:15)
    at Function.Module._load (internal/modules/cjs/loader.js:541:25)
    at Module.require (internal/modules/cjs/loader.js:677:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/Users/ofrobots/tmp/require-error/who-loaded-dis.js:1:63)
    at Module._compile (internal/modules/cjs/loader.js:748:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:759:10)
    at Module.load (internal/modules/cjs/loader.js:640:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:572:12)
    at Function.Module._load (internal/modules/cjs/loader.js:564:3)

I'm somewhat on the fence about the new lines error.message. I think this is the most useful presentation we can give to the user, but I do recognize that user-space may not be expecting newlines before the stacktrace (or have we crossed this bridge already in a different core error message?). Putting the entire string on the same line is possible, but that becomes less readable.

We have been telling users to not rely overly on the precise string, but rather the error codes, but I'm not sure if the ecosystem has absorbed that fully. If not, this would be considered a semver-major.

CI: https://ci.nodejs.org/job/node-test-pull-request/20767/ CI: https://ci.nodejs.org/job/node-test-pull-request/20771/

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

Merge request reports

Loading