Skip to content

require has issues when run from / #6679

New issue

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

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

Already on GitHub? # to your account

Closed
mhart opened this issue May 10, 2016 · 19 comments
Closed

require has issues when run from / #6679

mhart opened this issue May 10, 2016 · 19 comments
Labels
confirmed-bug Issues with confirmed bugs. module Issues and PRs related to the module subsystem.

Comments

@mhart
Copy link
Contributor

mhart commented May 10, 2016

  • Version: 6.1.0
  • Platform: Darwin ReBuke-Pro.local 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64 and Linux f50a089ff63e 4.4.8-boot2docker #1 SMP Mon Apr 25 21:57:27 UTC 2016 x86_64 Linux
  • Subsystem: require/modules

The following command works in v5/v4/v0.12/v0.10 with npm@2.15.5 or npm@3.8.9, works in v6 with npm@2.15.5, but fails in v6 with npm@3.8.9:

$ cd /
$ sudo npm install express
$ sudo node -p "require('express')"
...
module.js:440
    throw err;
    ^
Error: Cannot find module 'merge-descriptors'
    at Function.Module._resolveFilename (module.js:438:15)
    at Function.Module._load (module.js:386:25)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/node_modules/express/lib/express.js:16:13)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)

The following command works in v6 (and below):

$ sudo mkdir /app && cd /app && sudo npm install express && sudo node -p "require('express')"

You can reproduce this fairly easily without messing up your filesystem if you have docker (can use mhart/alpine-node instead of node below if you want a smaller download):

$ docker run node:5 sh -c 'npm install express && node -p "require(\"express\")"'

(^works)

$ docker run node:6 sh -c 'npm install express && node -p "require(\"express\")"'

(^doesn't work)

$ docker run node:6 sh -c 'mkdir app && cd app && npm install express && node -p "require(\"express\")"'

(^works)

It's unclear to me whether it's the fact that it's being run from the root directory specifically that's causing it to fail – or whether it's the presence of one of the other directories (eg, bin) that's getting in the way

@mhart mhart changed the title require fails when run from / require has issues when run from / May 10, 2016
@MylesBorins
Copy link
Contributor

@mhart thanks for reporting! would you be able to test this on v4 to see that it is indeed a regression in v6.

@MylesBorins MylesBorins added the module Issues and PRs related to the module subsystem. label May 10, 2016
@MylesBorins
Copy link
Contributor

It appears that this behavior is broken on v6, but works on v4 and v5.

I have a sneaking suspicion that #6537 is going to fix this.

What would be the best way of writing a regression test for this? I doubt we are going to want to be writing to "/" in ci

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

Building jasnell:revert-5950 as we speak – will let you know if it fixes the issue

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

Ok, I built jasnell:revert-5950 (468096d3f57a052c0d1ffc20a4464b9532c3dfb4), but no dice unfortunately...

$ node --version
v7.0.0-pre
$ cd /
$ npm install express
$ node -p "require('express')"
module.js:431
    throw err;
    ^
Error: Cannot find module 'merge-descriptors'
    at Function.Module._resolveFilename (module.js:429:15)
    at Function.Module._load (module.js:377:25)
    at Module.require (module.js:457:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/node_modules/express/lib/express.js:16:13)
    at Module._compile (module.js:532:32)
    at Object.Module._extensions..js (module.js:541:10)
    at Module.load (module.js:447:32)
    at tryModuleLoad (module.js:406:12)
    at Function.Module._load (module.js:398:3)

@MylesBorins
Copy link
Contributor

This leads me to believe it might be something in libuv /cc @saghul

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

Some more fuel to add to the fire: It works with v6 and npm@2 – so it must be something to do with the directory layout of node_modules and the way node is searching it – because with npm@3, all the modules (including merge-descriptors) are in /node_modules, whereas with npm@2 they're in /node_modules/express/node_modules

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

So if I do:

$ npm --version
3.8.9
$ node --version
v7.0.0-pre
$ npm install express
$ node -p "require('express')"
# errors
$ mkdir node_modules/express/node_modules
$ mv node_modules/* node_modules/express/node_modules/
# (ignore rename error)
$ ls node_modules
express
$ node -p "require('express')"
# works

@evanlucas
Copy link
Contributor

@mhart can you try running with the NODE_DEBUG=module environment variable set?

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

@evanlucas sure thing!

MODULE 27040: Module._load REQUEST vm parent: [eval]
MODULE 27040: load native module vm
MODULE 27040: Module._load REQUEST express parent: [eval]
MODULE 27040: looking for "express" in ["/node_modules","/root/.node_modules","/root/.node_libraries","/usr/lib/node"]
MODULE 27040: load "/node_modules/express/index.js" for module "/node_modules/express/index.js"
MODULE 27040: Module._load REQUEST ./lib/express parent: /node_modules/express/index.js
MODULE 27040: RELATIVE: requested: ./lib/express set ID to: /node_modules/express/index.js/lib/express from /node_modules/express/index.js
MODULE 27040: looking for "/node_modules/express/index.js/lib/express" in ["/node_modules/express"]
MODULE 27040: load "/node_modules/express/lib/express.js" for module "/node_modules/express/lib/express.js"
MODULE 27040: Module._load REQUEST events parent: /node_modules/express/lib/express.js
MODULE 27040: load native module events
MODULE 27040: Module._load REQUEST merge-descriptors parent: /node_modules/express/lib/express.js
MODULE 27040: looking for "merge-descriptors" in ["/node_modules/express/lib/node_modules","/node_modules/express/node_modules","/root/.node_modules","/root/.node_libraries","/usr/lib/node"]
module.js:431
    throw err;
    ^
Error: Cannot find module 'merge-descriptors'
    at Function.Module._resolveFilename (module.js:429:15)
    at Function.Module._load (module.js:377:25)
    at Module.require (module.js:457:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/node_modules/express/lib/express.js:16:13)
    at Module._compile (module.js:532:32)
    at Object.Module._extensions..js (module.js:541:10)
    at Module.load (module.js:447:32)
    at tryModuleLoad (module.js:406:12)
    at Function.Module._load (module.js:398:3)

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

So for some reason /node_modules isn't listed there in the final search

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

But it is in the first search (which is why express is found)

@mhart
Copy link
Contributor Author

mhart commented May 10, 2016

Here's the relevant output from v5:

MODULE 15: Module._load REQUEST vm parent: [eval]
MODULE 15: load native module vm
MODULE 15: Module._load REQUEST express parent: [eval]
MODULE 15: looking for "express" in ["//node_modules","/node_modules","/root/.node_modules","/root/.node_libraries","/usr/lib/node"]
MODULE 15: load "/node_modules/express/index.js" for module "/node_modules/express/index.js"
MODULE 15: Module._load REQUEST ./lib/express parent: /node_modules/express/index.js
MODULE 15: RELATIVE: requested: ./lib/express set ID to: /node_modules/express/index.js/lib/express from /node_modules/express/index.js
MODULE 15: looking for "/node_modules/express/index.js/lib/express" in ["/node_modules/express"]
MODULE 15: load "/node_modules/express/lib/express.js" for module "/node_modules/express/lib/express.js"
MODULE 15: Module._load REQUEST events parent: /node_modules/express/lib/express.js
MODULE 15: load native module events
MODULE 15: Module._load REQUEST merge-descriptors parent: /node_modules/express/lib/express.js
MODULE 15: looking for "merge-descriptors" in ["/node_modules/express/lib/node_modules","/node_modules/express/node_modules","/node_modules","/root/.node_modules","/root/.node_libraries","/usr/lib/node"]
MODULE 15: load "/node_modules/merge-descriptors/index.js" for module "/node_modules/merge-descriptors/index.js"
...

@evanlucas
Copy link
Contributor

yea, I wonder if this could be related to @mscdex's perf improvements?

@targos
Copy link
Member

targos commented May 11, 2016

This patch fixes the issue:

diff --git a/lib/module.js b/lib/module.js
index 344ea97..4589f21 100644
--- a/lib/module.js
+++ b/lib/module.js
@@ -253,7 +253,7 @@ if (process.platform === 'win32') {
     // note: this approach *only* works when the path is guaranteed
     // to be absolute.  Doing a fully-edge-case-correct path.split
     // that works on both Windows and Posix is non-trivial.
-    const paths = [];
+    const paths = ['/node_modules'];
     var p = 0;
     var last = from.length;
     for (var i = from.length - 1; i >= 0; --i) {

I'm not sure it is the correct approach and if a similar change has to be done for win32.

@saghul
Copy link
Member

saghul commented May 11, 2016

This leads me to believe it might be something in libuv /cc @saghul

The only relation between libuv and the module system is the use of realpath, I guess. Maybe an strace will show what paths are attempted, but we (libuv) have no control over that.

@targos
Copy link
Member

targos commented May 11, 2016

#6670 may fix this issue actually

@mhart
Copy link
Contributor Author

mhart commented May 11, 2016

@targos – confirmed, #6670 fixes this 👍

@ghost
Copy link

ghost commented May 20, 2016

I have a similar issue having v6.1.0 node and project in UNC share which I serve in Windows through a network drive Z:\ (or that could be any letter it does not matter).

...
module.js:440
throw err;
^
Error: Cannot find module 'orchestrator'

@omokehinde
Copy link

am having this issue trying to use nodeunit too test my code. it shows this error `module.js:440
throw err;
^

Error: Cannot find module '../modules/math'
at Function.Module._resolveFilename (module.js:438:15)
at Function.Module._load (module.js:386:25)
at Module.require (module.js:466:17)
at require (internal/module.js:20:19)
at Object. (C:\Users\omokehine1\workspace\my1stproject\test\test-
math.js:1:74)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:456:32)
at tryModuleLoad (module.js:415:12)
at Function.Module._load (module.js:407:3)`

cjihrig pushed a commit that referenced this issue Aug 10, 2016
The `p < nmLen` condition will fail when a module's name is end with
`node_modules` like `foo_node_modules`. The old logic will miss the
`foo_node_modules/node_modules` in node_modules paths.

TL;TR, a module named like `foo_node_modules` can't require any module
 in the node_modules folder.

Fixes: #6679
PR-URL: #6670
Reviewed-By: Evan Lucas <evanlucas@me.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
confirmed-bug Issues with confirmed bugs. module Issues and PRs related to the module subsystem.
Projects
None yet
Development

No branches or pull requests

7 participants