6

fields is undefined in the following code snipped, but it is not logged to the console when the error happens. In this specific instance, why, and what is the de facto way to handle this?

"Testing" is logged to the console (Line #2), but the undefined variable fields (Line #4) is not being reported. The error is returned in an API response (Line #5) but with no relevant information such as line #, stack trace, etc.

How can I make errors like this log to the console, and why are they not?

export function post(req, res) {
  console.log("Testing")
  User.create( getFields(req, ["name_first", "name_last"]) )
    .then(user =>  respondJSON (res, fields, { status: 201 }))
    .catch(err => respondError (res, err))
}

Since the catch is responding with an error, I get the following API response:

{
  "error": true,
  "data": {
    "message": "fields is not defined"
  }
}

I am using Babel 6 and babel-node to run my code through NPM scripts. I am using morgan logging as well. Removing the middleware for logging does not alter the error output.

Connorelsea
  • 2,040
  • 5
  • 22
  • 42
  • Do errors that happen in promises not propagate to the console? For example, if I just type `console.log(x)` into the Chrome console, it gives me `Uncaught ReferenceError: x is not defined` and a stack trace. – Connorelsea Sep 12 '16 at 01:42
  • Possible duplicate of [Why can I not throw inside a Promise.catch handler?](http://stackoverflow.com/questions/30715367/why-can-i-not-throw-inside-a-promise-catch-handler) – jib Sep 12 '16 at 04:30

3 Answers3

11

The automatic logging to console is a mechanism for unhandled exceptions. Because Promises automatically catch exceptions in the callbacks, the exceptions are no-longer unhandled, so nothing will be automatically logged.

If you want it to be logged, you could perhaps add a throw err at the end of your catch block. This will convert it into an unhandled promise rejection, which is typically handled similarly to an unhandled exception.

Jacob
  • 72,750
  • 22
  • 137
  • 214
  • Now I see some of the problems people have with promises. That kinda sucks. Thank you for explaining. – Connorelsea Sep 12 '16 at 01:49
  • 1
    The second part of the answer is incorrect. Throwing in `catch` won't affect anything. It may be listed as 'uncaught promise' error in latest Chrome versions, but not with Node native promises. – Estus Flask Sep 12 '16 at 01:53
  • 2
    @estus You need to re-throw for it to be considered an `unhandled rejection` but for those to log anywhere useful, your application also needs to log them manually. Chrome does it automatically, Node does not: https://nodejs.org/api/process.html#process_event_unhandledrejection – loganfsmyth Sep 12 '16 at 02:08
  • So how do people typically handle errors in promises? Any articles or writing on this topic either of you would recommend? Thanks! – Connorelsea Sep 12 '16 at 03:01
  • What @loganfsmyth listed works, handling that global `unhandledRejection` process event. If you want to convert it to an unhandled exception, you can throw within that event handler. – Jacob Sep 12 '16 at 03:28
  • How do devs usually handle stuff like this? Log in the catch? Or what you described? What is de facto? – Connorelsea Sep 12 '16 at 03:32
  • 2
    We have one node project where we did the throw within the `unhandledRejection` event to somewhat unify the two error system behaviors. For browser projects, we usually just let the default console logging behavior happen, but I know libraries like Bluebird offer more of a global event handler approach for browser apps. I'm not sure if there's an established defacto for this yet. IMO you either have expected or unexpected errors, and unless you have a defined behavior for the unexpected, there isn't really anything useful you can do short of logging. – Jacob Sep 12 '16 at 03:38
1

Because you didn't actually log the error?

export function post(req, res) {
  console.log("Testing")
  User.create( getFields(req, ["name_first", "name_last"]) )
    .then(user =>  respondJSON (res, fields, { status: 201 }))
    .catch(err => {
      console.error(err);
      respondError(res, err);
    });
}
Jason Livesay
  • 6,116
  • 3
  • 22
  • 30
  • Yeah I get that, but do errors like these not just show as an error? If I just type `console.log(x)` into the Chrome console, it gives me `Uncaught ReferenceError: x is not defined` and a stack trace. – Connorelsea Sep 12 '16 at 01:37
0

I had a similar problem caused by a 'finally' which was appended to the main async function running.

run()
.finally(()=>{process.exit(0)})

modifying it to:

run()
.catch(err => {console.log(err)})
.finally(()=>{process.exit(0)})

solved the problem

Nir
  • 887
  • 10
  • 19