A Better Way to Handle Errors in Node.js & Express.js

This article is going to explain why you should consider to use the NPM packages (@leismore/lmerror and @leismore/error_handler_last) to handle errors in your Node.js & Express.js applications.

Donation

Motivation

According to Express.js documentation - Error Handling, a typical error handling process in Express.js should be:

  1. Call next(error) function to pass an error to the error handler
  2. When received an error object, the error handler function should send proper HTTP response accordingly

Because the original JavaScript Error object does not carry any information about HTTP response, writing a general error handler could be a challenge.

By extending the Error class, @leismore/lmerror introduces a customized new Error class called LMError which describes not only an error message but also with precise HTTP response data. It also brings additional features such as Error Code and Previous Error Chain support.

With LMError, a standard error handler function (@leismore/error_handler_last) could be applied to any Node.js & Express.js application. This could greatly reduce the complexity of error handling.

Example

import * as express from 'express';
import {LMError} from '@leismore/lmerror';
import {error_handler_last} from '@leismore/error_handler_last';

const app = express();
const port = 3000;

class MyError extends LMError
{
/**
* Code Message
* error_1 something_wrong
* error_2 another_error
*/
}

app.get('/', (req:express.Request, res:express.Response, next:express.NextFunction) => {
let error = {message: 'something_wrong', code: 'error_1'};
let response = {
statusCode:'503',
headers:{'Content-Type':'application/json'},
body:{error: 'something_wrong'}
};

let previous_error = new Error('another_error');
next( new MyError(error, response, previous_error) );
});

// Add error handler
app.use(error_handler_last);

app.listen( port, () => console.log(`hello_world_error listening on port ${port}!`) );

The Hello-World demonstration application could be downloaded from GitHub:

Explanation

The NPM packages (@leismore/lmerror and @leismore/error_handler_last) provide:

  • LMError - A customized Error class supports Error-Message, Error-Code, HTTP-Response, Previous Error Chain
  • error_handler_last - A error handler function supports the standard JavaScript Error object, LMError object and http-errors object.

Usage Steps

  1. Import LMError and error_handler_last
  2. Define your app level error class by extending from LMError class
  3. Maintain an error message/code list for your application
  4. Pass any error to the error handler by calling next(MyError) in response handlers
  5. Use (app.use) error_handler_last as your last user-defined error handler

error_handler_last will catch all errors and send responses automatically:

  1. Send HTTP response according to HTTP response information within the Error object
  2. Send HTTP 500 if no HTTP response information received

Data Types

error:
{
  message: string // For human
  code: string // For machine
}

response:
{
statusCode: string // HTTP response code
headers: {key:value, key:value ...} // HTTP headers, optional
body: any // Literal object recommended (will be converted to JSON), optional
}


previous: Error object // Optional

Import LMError and error_handler_last

import {LMError}            from '@leismore/lmerror';
import {error_handler_last} from '@leismore/error_handler_last';

Define Your Error and Maintain a Error Message/Code List

class MyError extends LMError
{
/**
* Code Message
* error_1 something_wrong
* error_2 another_error
*/
}

Create Your Error

let error          = {message: 'something_wrong', code: 'error_1'};
let response = {
statusCode: '503',
headers: {'Content-Type':'application/json'},
body: {error: 'something_wrong'}
};

let previous_error = new Error('another_error');
next( new MyError(error, response, previous_error) );

Use error_handler_last

app.use(error_handler_last); // Make sure this is your last handler

You may insert your own error handler functions before error_handler_last:

function your_error_handler1(error, req, res, next)
{ ... }

function your_error_handler2(error, req, res, next)
{ ... }

app.use( your_error_handler1, your_error_handler2, error_handler_last );

Conclusion

The NPM packages (@leismore/lmerror and @leismore/error_handler_last) are introduced to improve the consistency of error handling mechanism in Node.js (Express.js). By extending the standard JavaScript Error class, they provide a more unified error processing method.

If you find it helpful, please do give them a star at GitHub (@leismore/lmerror and @leismore/error_handler_last). Your supports are important for me. Thank you.

Donation

Bugs

You would be appreciated for submitting any issue at GitHub:

Credit

 

Kyle Chine

Kyle Chine

An experienced full-stack web developer and certified open water diver living at Wollongong with family.

Read More