2 module.exports = errorHandler
5 , log = require("npmlog")
6 , npm = require("../npm.js")
7 , rm = require("rimraf")
9 , path = require("path")
10 , wroteLogFile = false
12 , rollbacks = npm.rollbacks
13 , chain = require("slide").chain
14 , writeStreamAtomic = require("fs-write-stream-atomic")
15 , nameValidator = require("validate-npm-package-name")
18 process.on("exit", function (code) {
19 // console.error("exit", code)
20 if (!npm.config || !npm.config.loaded) return
21 if (code) itWorked = false
22 if (itWorked) log.info("ok")
25 log.error("", "cb() never called!")
30 if (log.levels[log.level] <= log.levels.error) console.error("")
33 ["Please include the following file with any support request:"
34 ," " + path.resolve("npm-debug.log")
39 log.error("code", code)
43 var doExit = npm.config.get("_exit")
46 if (exitCode === 0 && !itWorked) {
49 if (exitCode !== 0) process.exit(exitCode)
51 itWorked = false // ready for next exit
55 function exit (code, noLog) {
56 exitCode = exitCode || process.exitCode || code
58 var doExit = npm.config ? npm.config.get("_exit") : true
59 log.verbose("exit", [code, doExit])
60 if (log.level === "silent") noLog = true
62 if (rollbacks.length) {
63 chain(rollbacks.map(function (f) {
64 return function (cb) {
65 npm.commands.unbuild([f], true, cb)
69 log.error("error rolling back", er)
70 if (!code) errorHandler(er)
71 else if (noLog) rm("npm-debug.log", reallyExit.bind(null, er))
72 else writeLogFile(reallyExit.bind(this, er))
74 if (!noLog && code) writeLogFile(reallyExit)
75 else rm("npm-debug.log", reallyExit)
80 else if (code && !noLog) writeLogFile(reallyExit)
81 else rm("npm-debug.log", reallyExit)
83 function reallyExit (er) {
84 if (er && !code) code = typeof er.errno === "number" ? er.errno : 1
86 // truncate once it's been written.
91 // just emit a fake exit event.
92 // if we're really exiting, then let it exit on its own, so that
93 // in-process stuff can finish or clean up first.
94 if (!doExit) process.emit("exit", code)
100 function errorHandler (er) {
101 // console.error("errorHandler", er)
102 if (!npm.config || !npm.config.loaded) {
103 // logging won't work unless we pretend that it's ready
104 er = er || new Error("Exit prior to config file resolving.")
105 console.error(er.stack || er.message)
109 er = er || new Error("Callback called more than once.")
113 if (!er) return exit(0)
114 if (typeof er === "string") {
117 } else if (!(er instanceof Error)) {
118 log.error("weird error", er)
122 var m = er.code || er.message.match(/^(?:Error: )?(E[A-Z]+)/)
123 if (m && !er.code) er.code = m
130 , "fstream_finish_call"
136 ].forEach(function (k) {
139 if (k === "fstream_stack") v = v.join("\n")
143 log.verbose("cwd", process.cwd())
145 var os = require("os")
146 // log.error("System", os.type() + " " + os.release())
147 // log.error("command", process.argv.map(JSON.stringify).join(" "))
148 // log.error("node -v", process.version)
149 // log.error("npm -v", npm.version)
150 log.error("", os.type() + " " + os.release())
151 log.error("argv", process.argv.map(JSON.stringify).join(" "))
152 log.error("node", process.version)
153 log.error("npm ", "v" + npm.version)
160 ].forEach(function (k) {
162 if (v) log.error(k, v)
166 if (log.levels[log.level] <= log.levels.error) console.error("")
171 log.error("", ["\nIf you are behind a proxy, please make sure that the"
172 ,"'proxy' config is set properly. See: 'npm help config'"
179 log.error("", ["\nPlease try running this command again as root/Administrator."
184 log.error("", er.message)
185 log.error("", ["","Failed at the "+er.pkgid+" "+er.stage+" script '"+er.script+"'."
186 ,"This is most likely a problem with the "+er.pkgname+" package,"
187 ,"not with npm itself."
188 ,"Tell the author that this fails on your system:"
190 ,'You can get information on how to open an issue for this project with:'
191 ,' npm bugs ' + er.pkgname
192 ,'Or if that isn\'t available, you can get their info via:',
193 ,' npm owner ls ' + er.pkgname
194 ,"There is likely additional logging output above."
199 log.error("", er.message)
200 log.error("", ["","Failed using git."
201 ,"This is most likely not a problem with npm itself."
202 ,"Please check if you have git installed and in your PATH."
207 log.error("", er.message)
208 log.error("", "File: "+er.file)
209 log.error("", ["Failed to parse package.json data."
210 ,"package.json must be actual JSON, not just JavaScript."
211 ,"","This is not a bug in npm."
212 ,"Tell the package author to fix their package.json file."
213 ].join("\n"), "JSON.parse")
217 // Add a special case here for E401 and E403 explaining auth issues?
220 var msg = [er.message]
221 if (er.pkgid && er.pkgid !== "-") {
222 msg.push("", "'" + er.pkgid + "' is not in the npm registry.")
224 var valResult = nameValidator(er.pkgid)
226 if (valResult.validForNewPackages) {
227 msg.push("You should bug the author to publish it (or use the name yourself!)")
229 msg.push("Your package name is not valid, because", "")
231 var errorsArray = (valResult.errors || []).concat(valResult.warnings || [])
232 errorsArray.forEach(function(item, idx) {
233 msg.push(" " + (idx + 1) + ". " + item)
238 msg.push("It was specified as a dependency of '"+er.parent+"'")
240 msg.push("\nNote that you can also install from a"
241 ,"tarball, folder, http url, or git url.")
243 // There's no need to have 404 in the message as well.
244 msg[0] = msg[0].replace(/^404\s+/, "")
245 log.error("404", msg.join("\n"))
248 case "EPUBLISHCONFLICT":
249 log.error("publish fail", ["Cannot publish over existing version."
250 ,"Update the 'version' field in package.json and try again."
252 ,"To automatically increment version numbers, see:"
258 log.error("git", [er.message
260 ,"Refusing to remove it. Update manually,"
261 ,"or move it out of the way first."
266 log.error("cycle", [er.message
267 ,"While installing: "+er.pkgid
268 ,"Found a pathological dependency case that npm cannot solve."
269 ,"Please report this to the package author."
274 log.error("notsup", [er.message
275 ,"Not compatible with your operating system or architecture: "+er.pkgid
276 ,"Valid OS: "+er.os.join(",")
277 ,"Valid Arch: "+er.cpu.join(",")
278 ,"Actual OS: "+process.platform
279 ,"Actual Arch: "+process.arch
284 log.error([er.message
285 ,"File exists: "+er.path
286 ,"Move it away, and try again."].join("\n"))
290 log.error("need auth", [er.message
291 ,"You need to authorize this machine using `npm adduser`"
296 var peerErrors = Object.keys(er.peersDepending).map(function (peer) {
297 return "Peer " + peer + " wants " + er.packageName + "@"
298 + er.peersDepending[peer]
300 log.error("peerinvalid", [er.message].concat(peerErrors).join("\n"))
307 log.error("network", [er.message
308 ,"This is most likely not a problem with npm itself"
309 ,"and is related to network connectivity."
310 ,"In most cases you are behind a proxy or have bad network settings."
311 ,"\nIf you are behind a proxy, please make sure that the"
312 ,"'proxy' config is set properly. See: 'npm help config'"
316 case "ENOPACKAGEJSON":
317 log.error("package.json", [er.message
318 ,"This is most likely not a problem with npm itself."
319 ,"npm can't find a package.json file in your current directory."
324 var msg = [er.message
325 ,"This is most likely not a problem with npm itself."
326 ,"In most cases you or one of your dependencies are requesting"
327 ,"a package version that doesn't exist."
330 msg.push("\nIt was specified as a dependency of '"+er.parent+"'\n")
332 log.error("notarget", msg.join("\n"))
337 log.error("notsup", [er.message
338 ,"Not compatible with your version of node/npm: "+er.pkgid
339 ,"Required: "+JSON.stringify(er.required)
341 +JSON.stringify({npm:npm.version
342 ,node:npm.config.get("node-version")})
345 } // else passthrough
348 log.error("nospc", [er.message
349 ,"This is most likely not a problem with npm itself"
350 ,"and is related to insufficient space on your system."
355 log.error("rofs", [er.message
356 ,"This is most likely not a problem with npm itself"
357 ,"and is related to the file system being read-only."
358 ,"\nOften virtualized file systems, or other file systems"
359 ,"that don't support symlinks, give this error."
364 log.error("enoent", [er.message
365 ,"This is most likely not a problem with npm itself"
366 ,"and is related to npm not being able to find a file."
367 ,er.file?"\nCheck if the file '"+er.file+"' is present.":""
372 log.error("eisdir", [er.message
373 ,"This is most likely not a problem with npm itself"
374 ,"and is related to npm not being able to find a package.json in"
375 ,"a package you are trying to install."
380 log.error("", er.message || er)
381 log.error("", ["", "If you need help, you may report this error at:"
382 ," <https://github.com/npm/npm/issues>"
387 exit(typeof er.errno === "number" ? er.errno : 1)
390 var writingLogFile = false
391 function writeLogFile (cb) {
392 if (writingLogFile) return cb()
393 writingLogFile = true
396 var fstr = writeStreamAtomic("npm-debug.log")
400 log.record.forEach(function (m) {
401 var pref = [m.id, m.level]
402 if (m.prefix) pref.push(m.prefix)
403 pref = pref.join(" ")
405 m.message.trim().split(/\r?\n/).map(function (line) {
406 return (pref + " " + line).trim()
407 }).forEach(function (line) {