Node.js: The error object

Node.js: The error object

Errors should be handled using the Error object provided by Node.js, whether it is in synchronous functions

Errors should be handled using the Error object provided by Node.js, whether it is in synchronous functions using exceptions or in asynchronous functions passing the error through the callback.

Here we will see how to use this object and how to extend from it in order to create our own types of errors.

Strings are not errors

We should not use strings as errors since that reduces the interoperability between modules.

function doStuff (callback) {
  // ...
  asyncRequest('http://example.com', function (response) {
    // ...
    if (response.statusCode != 200) {
      callback('Error: request status code: ' + response.statusCode);
    } 
    // ...
  });
  // ...
}

As we will see, it is much more convenient to use the Error object.

What is the Error object?

It is a native object of Node.js which provides standard information, such as the stacktrace, the name and the message of the error. The most important fields are:

  • name: Used to distinguish between error types at a broad level.
  • message: Description of the error. It should be thorough enough so anyone who reads it can understand it. If we propagate the error through callbacks, it may be useful to expand this message by adding further information at each level.
  • stack: The stacktrace is obtained by V8 (the javascript engine Node.js runs on) and, in general, it is not a good idea to expand it since this property is calculated only when accessed to (for performance-related reasons).

Example:

function doStuff (callback) {
  // ...
  asyncRequest('http://example.com', function (response) {
    // ...
    if (response.statusCode != 200) {
      var error = new Error('example.com request status code not OK');
      error.name = 'requestNotOk';
      error.httpStatusCode = response.statusCode
      callback(error);
    } 
    // ...
  });
  // ...
}

Here we create an error object; the builder defines the message property. We also add a personalized property to it, so as to show the http code returned and, finally, we call the callback by means of this object.

Extending the Error object

We can extend the Error object to have more control over the error handling, as well as to be able to use instanceof errorType. When we extend it, it is important to use Error.captureStackTrace to create the stack property in our new object, as shown below:

var util = require('util');

function customError(message) {
        this.name = this.constructor.name;
        this.message = message;

        //include stack trace in error object
        Error.captureStackTrace(this, this.constructor);
}

util.inherits(customError, Error);

var err = new customError('my error');
console.log(err instanceof customError); //true
console.log(err); // {[customError] name: 'customError', message: 'my error'}
console.log(err.stack); // -> stacktrace

Extend-error
extend-error is a module that facilitates the extension of the Error object. To use it, we just have to make require(‘extend-error’) and it will create a method extend inside the Error object. Then, we just use Error.extend(‘ErrorName’, errorCode) to create our own errors (errorCode is optional).

In the following example we will create a personalized error called ClientError with code 400, and then, from this error, we will extend another one called HttpNotFound with code 404.

require('extend-error');

var ClientError = Error.extend('ClientError', 400);
var HttpNotFound = ClientError.extend('HttpNotFound', 404);

var myHttpNotFound = new HttpNotFound('my error message');

// Output: true
console.log(myHttpNotFound instanceof HttpNotFound);

// Output: true
console.log(myHttpNotFound instanceof ClientError);

// Output:
// { [HttpNotFound: my error message]
//   name: 'HttpNotFound',
//   code: 404,
//   message: 'my error message' }
console.log(myHttpNotFound);

Recommended literature: