Skip to content

RelayIN/error-handler

Repository files navigation

@relayin/error-handler

Errors management at relay

Relay error handler is a package used by Node.js micro services to return consistent error nodes from the API response.

Table of contents

Types of errors/exceptions

Before getting started, let's distinguish between the types of error an application can have and why having a consistent output is important.

Validation errors

Validation errors are the most straight forward one's. The service validates the user input and returns one or more errors, when the incoming data is not valid.

We make use of indicative for running data validations. Indicative offers an API to define error formatters, can be used to re-shape the errors array.

This module (relayin/error-handler) configures a custom error formatter with Indicative to have a consistent validation error nodes.

Flow exceptions

The flow exceptions occurs, when a backend service peforms inline checks before taking certain actions. Notice we make use keyword exception and not error. Their is a slight difference between error and exception. For example:

A client makes a request to one of our service and we notice that their account is invalid. At first place, they shouldn't be able to make this request with an invalid account.

Flow exceptions occurs when a request reaches a guard intentionally added for extra security.

Unexcepted exceptions

As the name says, unexpected exceptions are unanticipated exceptions that must be handled gracefully and logged to the system for further inspection.

How do we handle them?

At relay, we make sure to uniquely identify an error or exception with a numeric code like 10001. The numeric codes are inspired from twilio and has following benefits.

  1. You don't have to think hard for unique names. Simply increment the error and write documentation for it.
  2. It's easier to have unique code per micro service. Assign a numeric bucket like 1000 to auth and 2000 to directory and so on.

The numeric codes not only makes it easier to identify the error. It gives freedom to the clients to display error messages in the user language by mapping them against the code.

Shape of error objects

The shape of error objects is driven by jsonapi spec and looks as follows.

{
  code: 10001,
  title: 'Generic error message title in english',
  source: {
    pointer: 'data/field/reference',
  },
}

The source object will be removed when error is not related to a field.

{
  code: 10002,
  title: 'Inactive account',
}

Usage

Finally let's jump on the usage of this module. It automatically configures an exception handler for AdonisJs and a error formatter for Indicative.

Install it from npm as follows:

npm i @relayin/error-handler

and then use it as a service provider inside start/app.ts file.

export const providers = [
  '@relayin/error-handler/build/providers/ErrorHandlerProvider'
]

Finally, within the app exception handler you can use Relay/ExceptionManager to convert Exceptions to api response objects.

const ExceptionManager = use<Relay.ExceptionManager>('Relay/ExceptionManager')

class ExceptionHandler {
  async handle (error, { response }: AdonisJs.Context) {
    const { status, errors } = ExceptionManager.toResponse(error)
    response.status(status).send({ errors })
  }
}

That's all from the usage point of view. The validation errors gets a unique set of error codes, which are shared by all micro service and you won't have to do much on that front.

Defining codes for exceptions

For exceptions, you need to create a config file config/errorCodes.ts and define codes for them.

export const exceptionCodes = {
  ERR_GATEWAY_FAILURE: 20001,
  ERR_MISSING_OTP: 20001,
  ERR_INVALID_OTP_LENGTH: 20001,
  ERR_MISSING_MOBILE_NUMBER: 20001,
  ERR_UNKNOWN_GATEWAY_FAILURE: 20001,
}

export const errorCodes = {
  20001: {
    message: 'Unable to send SMS. Try again after some time'
  },
}

export const codesBucket = 20000

Following is the explaination for the config file.

  • exceptionCodes: Exception codes are logged to the logging service. They are used for debugging and should never be exposed to the client.
  • errorCodes: The errorCodes is the list of codes and their generic messages, you want to return to the client. It is possible that for multiple exceptions you want to return a generic code to the client, sicne they don't take if sending SMS failed coz of E_GATEWAY_FAILURE or E_INVALID_API_KEY.
  • codesBucket: The bucket ensures that you always use numeric codes within the range of your bucket and avoid conflicts with micro services.

Change log

The changelog can be found in the CHANGELOG.md file.