Skip to content
This repository has been archived by the owner on Aug 11, 2022. It is now read-only.
This repository has been archived by the owner on Aug 11, 2022. It is now read-only.

Lifecycle scripts silently fail on win32 if cmd.exe is not on the PATH #5267

Closed
@edmorley

Description

Using node v0.10.28 and npm v1.4.9 on Windows 8.1 x64, inside an MSYS bash shell (where the path is overridden by my .bashrc for other reasons):
package.json:

{
  "scripts": {
    "postinstall": "echo foo"
  }
}

Output:

[/c/npmtest]$ echo $PATH
.:/c/Python27:/c/Python27/Scripts:/mingw/bin:/bin:/c/Program Files/nodejs:/c/Users/Ed/AppData/Roaming/npm
[/c/npmtest]$ npm install
npm WARN package.json @ No description
npm WARN package.json @ No repository field.
npm WARN package.json @ No README data

> @ postinstall c:\npmtest
> echo foo


[/c/npmtest]$ export PATH="$PATH:/c/Windows/System32"
[/c/npmtest]$ npm install
npm WARN package.json @ No description
npm WARN package.json @ No repository field.
npm WARN package.json @ No README data

> @ postinstall c:\npmtest
> echo foo

foo

npm-debug.log from the failed (first) |npm install| above:

19 info postinstall @
20 verbose unsafe-perm in lifecycle true
21 error Error: spawn ENOENT
21 error     at errnoException (child_process.js:998:11)
21 error     at Process.ChildProcess._handle.onexit (child_process.js:789:34)
22 error If you need help, you may report this *entire* log,
22 error including the npm and node versions, at:
22 error     <http://github.com/npm/npm/issues>
23 error System Windows_NT 6.2.9200
24 error command "c:\\Program Files\\nodejs\\node.exe" "c:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
25 error cwd c:\npmtest
26 error node -v v0.10.28
27 error npm -v 1.4.9
28 error syscall spawn
29 error code ENOENT
30 error errno ENOENT
31 verbose exit [ 1, true ]

Similar to nodejs/node-v0.x-archive#7616, this is caused by using 'cmd' without an absolute path, and thus relying on it being present on the PATH. More frustratingly the |npm install| appears to succeed, meaning it took some time before I realised it hadn't and so looked at npm-debug.log

As such, I think:

  1. The spawn ENOENT should be output using log.error(), rather than swallowed silently here:

    npm/lib/utils/lifecycle.js

    Lines 212 to 238 in bf761dd

    var proc = spawn(sh, [shFlag, cmd], conf)
    proc.on("close", function (code, signal) {
    if (signal) {
    process.kill(process.pid, signal);
    } else if (code) {
    var er = new Error("Exit status " + code)
    }
    if (er && !npm.ROLLBACK) {
    log.info(pkg._id, "Failed to exec "+stage+" script")
    er.message = pkg._id + " "
    + stage + ": `" + cmd +"`\n"
    + er.message
    if (er.code !== "EPERM") {
    er.code = "ELIFECYCLE"
    }
    er.pkgid = pkg._id
    er.stage = stage
    er.script = cmd
    er.pkgname = pkg.name
    return cb(er)
    } else if (er) {
    log.error(pkg._id+"."+stage, er)
    log.error(pkg._id+"."+stage, "continuing anyway")
    return cb()
    }
    cb(er)
    })
  2. We could be nice and use:
sh = process.env.comspec || "cmd"

...here:

sh = "cmd"

...where process.env.comspec is the full path to the default interpreter (eg: "C:\Windows\System32\cmd.exe").

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions