Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Custom ES6 errors in Node.js

Here's how you could create custom error classes in Node.js using latest ES6 / ES2015 syntax.

I've tried to make it as lean and unobtrusive as possible.

Defining our own base class for errors

errors/AppError.js

module.exports = class AppError extends Error {
  constructor (message, status) {
  
    // Calling parent constructor of base Error class.
    super(message);
    
    // Saving class name in the property of our custom error as a shortcut.
    this.name = this.constructor.name;

    // Capturing stack trace, excluding constructor call from it.
    Error.captureStackTrace(this, this.constructor);
    
    // You can use any additional properties you want.
    // I'm going to use preferred HTTP status for this error types.
    // `500` is the default value if not specified.
    this.status = status || 500;
    
  }
};

Defining specific error types

errors/EmailTakenError.js

module.exports = class EmailTakenError extends require('./errors/AppError') {
  constructor (message) {
    // Providing default message and overriding status code.
    super(message || 'Specified E-Mail is already taken', 400);
  }
};

errors/RequestValidationError.js

module.exports = class extends require('./AppError') {
  constructor (fields) {
    // Overriding both message and status code.
    super('Request validation failed', 400);
    // Saving custom property.
    this.fields = fields || {};
  }
};

Throwing and catching

const AppError = require('./../api/errors/AppError');
const EmailTakenError = require('./../api/errors/EmailTakenError');
const RequestValidationError = require('./../api/errors/RequestValidationError');


try {
  // Throwing EmailTakenError exception.
  throw new EmailTakenError();
} catch (error) {
  // Catching exception by class.
  if (error instanceof EmailTakenError) {
    console.log('E-Mail validation failed!', error);
  } else {
    // If failed to catch, throwing it higher.
    console.log('Unknown error', error);
    throw error;
  }
}


try {
  // Throwing RequestValidationError exception.
  throw new RequestValidationError();
} catch (error) {
  // Catching error by base (parent) class.
  if (error instanceof AppError) {
    console.log('Some application error occurred!', error);
  } else {
    console.log('Unknown error', error);
    throw error;
  }
}

Feedback

It works great for my application, however cirtisim is welcomed.

@olegsu

This comment has been minimized.

Show comment Hide comment
@olegsu

olegsu Feb 18, 2017

Just a small order fix

    // Saving class name in the property of our custom error as a shortcut.
    this.name = this.constructor.name;
    // Capturing stack trace, excluding constructor call from it.
    Error.captureStackTrace(this, this.constructor);

This way the stacktrace will hold the name as well

olegsu commented Feb 18, 2017

Just a small order fix

    // Saving class name in the property of our custom error as a shortcut.
    this.name = this.constructor.name;
    // Capturing stack trace, excluding constructor call from it.
    Error.captureStackTrace(this, this.constructor);

This way the stacktrace will hold the name as well

@fgarcia

This comment has been minimized.

Show comment Hide comment
@fgarcia

fgarcia Apr 21, 2017

Extending Errors with ES6 classes has one minor downside: you are forced to use the new operator, while the native Error() object is a factory by itself.

Both of this statements work

throw Error()
throw new Error()

While this will fail

throw EmailTakenError();

But the approach is clearly the most modern solution

fgarcia commented Apr 21, 2017

Extending Errors with ES6 classes has one minor downside: you are forced to use the new operator, while the native Error() object is a factory by itself.

Both of this statements work

throw Error()
throw new Error()

While this will fail

throw EmailTakenError();

But the approach is clearly the most modern solution

@masiamj

This comment has been minimized.

Show comment Hide comment
@masiamj

masiamj May 16, 2017

This looks awesome! I'm just having trouble actually capturing the stacktrace. Is this working for you?

masiamj commented May 16, 2017

This looks awesome! I'm just having trouble actually capturing the stacktrace. Is this working for you?

@gezza-b

This comment has been minimized.

Show comment Hide comment
@gezza-b

gezza-b Jun 24, 2017

I really like this Error class approach and I added a print() method to the class to help me with error tracing.
However, it does not work when I move the error class to a separate module. Can I do that in the class or do I need a prototype?

gezza-b commented Jun 24, 2017

I really like this Error class approach and I added a print() method to the class to help me with error tracing.
However, it does not work when I move the error class to a separate module. Can I do that in the class or do I need a prototype?

@herlon214

This comment has been minimized.

Show comment Hide comment
@herlon214

herlon214 Oct 5, 2017

Thanks! This is really what I wanted.

Thanks! This is really what I wanted.

@momocow

This comment has been minimized.

Show comment Hide comment
@momocow

momocow Nov 1, 2017

@gezza-b After moving the error class to a separate module, you should export the error class and use require to import it. Maybe you can provide an example here.

@fgarcia A wrapper function is needed if you want to handle the use with and without new.

errors/EmailTakenError.js

module.exports = function(){
    return new EmailTakenError()
}

Hoewever, using the new operator make it more clearly that it returns an instance of a class. (And it is only 3 letters longer)
It is all up to your preference, though.

momocow commented Nov 1, 2017

@gezza-b After moving the error class to a separate module, you should export the error class and use require to import it. Maybe you can provide an example here.

@fgarcia A wrapper function is needed if you want to handle the use with and without new.

errors/EmailTakenError.js

module.exports = function(){
    return new EmailTakenError()
}

Hoewever, using the new operator make it more clearly that it returns an instance of a class. (And it is only 3 letters longer)
It is all up to your preference, though.

@PaulSebi

This comment has been minimized.

Show comment Hide comment
@PaulSebi

PaulSebi Nov 13, 2017

Hey, if you'd like an easy way to manage error Codes, check out snerr
npm
github

Hey, if you'd like an easy way to manage error Codes, check out snerr
npm
github

@wickd

This comment has been minimized.

Show comment Hide comment
@wickd

wickd Dec 21, 2017

thank you, very useful :)

wickd commented Dec 21, 2017

thank you, very useful :)

@Maxtermax

This comment has been minimized.

Show comment Hide comment
@Maxtermax

Maxtermax Jan 3, 2018

nice

nice

@DaneTheory

This comment has been minimized.

Show comment Hide comment
@DaneTheory

DaneTheory Mar 20, 2018

fantastic tutorial. Mind is blown on how slim the codebase is to pull this off. thanks!

fantastic tutorial. Mind is blown on how slim the codebase is to pull this off. thanks!

@izorsa

This comment has been minimized.

Show comment Hide comment
@izorsa

izorsa May 15, 2018

nice, thanks!

izorsa commented May 15, 2018

nice, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment