1

First of all, I know one way to catch uncaught errors is use process.on('uncaughtException', err, function() {});.

I want to know how I can pass more details, or more context to the error. I want to be able to get the variables used. I'm not trying to recover from the error, only get more details of my environment when the error happened before shutting down the process. Yeah, the stack trace is nice, but I'd like to know how to replicate the error.

For example, I have this function:

function doTheBatman(var1) {
  var var2 = 'whatever';
  // this causes an uncaught exception later in the code
}

On process.on, I want to be able to access var1 and var2.

process.on('uncaughtException', function(err) {
  // process.whatever doesn't contain any active variables
});
7
  • Are you aware you can add an express route error handler? It's basically overloading the route definition with an error-handling function. Commented Jul 27, 2018 at 22:55
  • You're right, I updated my question. I also want to get variables that exist in a function out of the express context. Commented Jul 27, 2018 at 23:17
  • I also want to get variables that exist in a function out of the express context - which variables and contexts? The express error handler should give you access to the req, combine that with the stack trace and...I'm wondering what other variables you would need for diagnosis? Commented Jul 27, 2018 at 23:22
  • In my testing, I'm unable to catch uncaught exceptions using app.use(function(err...) {}) (I do have it defined at the very end) when they occur in a function that does not pass the req variables as an arugment, at least without using the process.on method I describe above. The variables can be anything passed as an argument or generated inside the function. Commented Jul 27, 2018 at 23:28
  • 1
    Sorry, I'm having quite a bit of difficulty picturing where the errors occur in relation to your express routes, and what is holding what data. Could you post some more code? Commented Jul 27, 2018 at 23:32

2 Answers 2

0

A synchronous exception in an Express route handler will be caught by Express itself and the exception will be passed off the default Express error handler where you can catch it yourself and the exception context is passed to that default express error handler.

You can see this code inside of Express where a route handler gets called:

Layer.prototype.handle_request = function handle(req, res, next) {
  var fn = this.handle;

  if (fn.length > 3) {
    // not a standard request handler
    return next();
  }

  try {
    fn(req, res, next);
  } catch (err) {
    next(err);
  }
};

The call to next(err) will pass the exception object off to the default Express error handler (which you can install a handler for).


If your code is throwing an exception inside of an asynchronous callback, then that is more complicated to catch in action. If you're using regular async callbacks (not promises), then the only way I know of to catch those at a meaningful spot is to put a try/catch inside of every async callback so you can capture the local stack info.

If you use promises at the lowest level and only program your logic and asynchronous code flow use promise functionality, then an exception in a promise handler will automatically turn into a rejected promise and certain promise libraries (like the Bluebird library can be configured to give you a pretty full stack trace of where things went wrong). Promises have this advantage because every promise .then() or .catch() handler is automatically wrapped in a try/catch handler and those are turned into promise rejections which propagate up the chain to the first .catch() handler they find.


For the non-Express example you just added to your question, you will just have to put a try/catch somehwere in the local neighborhood to catch a local synchronous exception:

function doTheBatman(var1) {
  try {
      var var2 = 'whatever';
      // this causes an uncaught exception later in the code
  } catch(e) {
      console.log(e);
  }
}

You can even set a debugger breakpoint in the catch handler and then examine variables in that scope when it is hit. I don't know of any way to examine the local variables at the point of the exception from the uncaughtException handler. err.stack should give you the stack trace, but not variable values.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer. I have my own reporting function that can accept an object of variables when an error happens, but I would have to know when the error is likely to happen. Putting try...catch every where on my code is impractical for me, but would technically work if I were to put the time and effort into doing it every time I write more code. I would rather fallback on process.on and pass variables if possible.
Well, process.on('uncaughtException, ...)` will give you the stack trace in err.stack, but not the variables in each scope of the stack trace. If you're trying to write a robust server, you have to catch exceptions before process.on('uncaughtException, ...)` anyway because at that point, you've lost the ability to handle the exception gracefully in an appropriate local context. Robust server code requires try/catch handlers around any code that has unchecked input or parameters or that can throw an exception. You either have to catch the exception locally or prevent the exception.
That's true, and for ~99% of my code, I do my own error logic. However, I'm not perfect and I will sometimes screw something up, or my code fails to catch something. I have process.on as a last ditch resort to report errors.
@JM-AGMS - Well, it appears you're asking for a feature that does not exist. I'm just telling you how it works today. I understand why one would log uncaughtException, but that will give you a stack trace which may take a lot more debugging and probably some additional instrumentation to find out what caused the uncaughtException in the first place which should then ultimately result in adding more try/catch to your code as the long term solution. I too wish the uncaughtException error object would give you everything you might need to solve the problem, but it doesn't.
0

Express/frameworks may offer more elegant/robust solutions, but if you're truly after what your question asks for... why not just capture variables outside of the functions scope? This is typically nasty and not considered best practice, but if you have a function that you know could be susceptive to failing often, perhaps the quick and dirty solution is what you need. You could always refine this later, but hopefully this demonstrates the approach...

var transactionVars = {};

function clearTransaction() {
  transactionVars = {};
}

function doTheBatman(var1) {
  transactionVars['var2'] = 'whatever';
  // [...] bunch of stuff, possibly blowing up...
  clearTransaction(); // we made it this far? cool, reset...
}

process.on('uncaughtException', function(err) {
  console.log(transactionVars['var2']); // whatever
});

Furthermore, if you want to really dirty (in case these two functions are in two files) you can always tack transactionVars on the global object.

This is essentially a poor mans event emitter pattern, which I would highly recommend refactoring into once you grasp the general flow of how this works...

2 Comments

haha, I suppose that could work and using it directly on process would save a step, redeclaring the variable again at the start of the function would also save another step. But its up there with defining try...catch (which would be a better practice) on all my code and is a lot of error handling to maintain.
@JM-AGMS yea, its up to you how meticulous you want to be with try...catch I feel like OCD level error handling is okay and will serve you well. This approach is just about the total opposite, but if you find value in a global "catch all" error hander than affords you to inspect stateful variables, well, this would suffice