2

I am currently trying to handle exceptions and errors in a NodeJS app which will be used for critical information. I need a clean error management ! I've been wondering if there is something similar to Java Exceptions encapsulation.

I'm explaning.

In Java you can do something like that :

try {
    // something that throws Exception
} catch (Throwable t) {
    throw new Exception("My message", t);
}

That allows you to decide when to log your exception and you get the whole stack trace and call path !

I would like to know if there is a way to do the same in NodeJS because logging at every step seems not to be the right way of doing things.

Thank you.

Bidi
  • 51
  • 7

3 Answers3

1

You should look at this module : https://www.npmjs.com/package/verror

Joyent quote it on his error management best pratices : https://www.joyent.com/developers/node/design/errors

At Joyent, we use the verror module to wrap errors since it's syntactically concise. As of this writing, it doesn't quite do all of this yet, but it will be extended to do so.

It allow you to get details on error message. And tracking the step of the error.

And also hide details to the client with wrapped error : WError() who returns only the last error message.

Sachacr
  • 704
  • 1
  • 9
  • 17
  • Thank you i'll get a look at that ! – Bidi May 26 '16 at 12:55
  • That is the kind of things i was looking for but why is it not native ?! Anyway, thank you ! – Bidi May 26 '16 at 13:31
  • That library is nice but it is half finished. When you encapsulate a previous error A into error B. The final message is correct but the stack trace is only of B :'( – Bidi May 26 '16 at 14:10
1

I answer my own question to explain what i finaly did to have the wanted encapsulation. I used https://www.npmjs.com/package/verror as Sachacr suggested.

Then I extended it that way :

my_error.js :

var VError          = require('verror');
var _               = require('lodash');

function MyError() {
    var args = [];

    var httpErrorCode;
    var cause;

    if (arguments.length > 0) {
        var lastArgumentIndex = [arguments.length];

        cause = manageCause(lastArgumentIndex, arguments);
        httpErrorCode = manageHttpCode(lastArgumentIndex, arguments);

        for (var i = 0; i < lastArgumentIndex; i++) {
            args[i] = arguments[i];
        }
    }

    this.__proto__.__proto__.constructor.apply(this, args);

    if (cause) {
        if (this.stack) {
            this.stack += '\n' + cause.stack;
        } else {
            this.stack = cause.stack;
        }
    }

    this.httpErrorCode = httpErrorCode;
}

MyError.prototype.__proto__ = VError.prototype;

function manageCause(lastArgumentIndex, arguments) {
    if (lastArgumentIndex[0] > 0
        && arguments[lastArgumentIndex[0] - 1] instanceof Error) {

        lastArgumentIndex[0]--;
        return arguments[lastArgumentIndex[0]];
    }
}

function manageHttpCode(lastArgumentIndex, arguments) {
    if (lastArgumentIndex[0] > 0
        && _.isNumber(arguments[lastArgumentIndex[0] - 1])) {

        lastArgumentIndex[0]--;
        return arguments[lastArgumentIndex[0]];
    }
}

module.exports = MyError;

It allows me to use it easily in my code :

var MyError = require('./my_error.js');

function withErrors() {
    try {
        // something with errors
    } catch (err) {
        // This is the same pattern as VError
        return new MyError("My message", err, 401);
    }
}

function somethingToDo(req, res) {
    var result = withErrors();

    if (result instanceof MyError) {
        logger.warn(result);
        res.status(result.httpErrorCode).send(result.message).end();
        return
    }
}

That way, i hace a nice stack trace with call path and every line involved in error/exception.

Hope it will help people, cause i searched a looooong time :)

EDIT : I modified my MyError class to add HTTP Error codes and clean arguments management.

Bidi
  • 51
  • 7
0

You should be able to do something like:

funtion exception(message, error) {
    this.message = message;
    this.stacktrace = error.stack;
}

try {
   if(someData == false)
      throw new exception("something went wrong!", new Error());
}
catch(ex) {
    console.log(ex.message);
    console.log(ex.stacktrace);
}

You can then throw your own custom exception instance containing whatever debugging info you need.

EDIT: added stack trace to exception object

Base33
  • 3,167
  • 2
  • 27
  • 31
  • The point is I don't want to log it straight away. I want my calling function to get that error and manage it (may be log it, may be throw it, ...). Because if I log it now, I have no idea of the whole context. So I want to propogate without loosing any info. – Bidi May 26 '16 at 12:30
  • So there is no native way to properly handle Errors propagation ? Do I have to create my own structure ? – Bidi May 26 '16 at 12:32
  • NodeJS is just the javascript engine from chromium with a few bells and whistles. Unless there is a node package available, I am not aware of any native way currently. – Base33 May 26 '16 at 14:52