Skip to content

Instantly share code, notes, and snippets.

@kerimdzhanov
Forked from justmoon/custom-error.js
Last active March 21, 2020 18:37
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save kerimdzhanov/29b9117f2b6a2d3034b2 to your computer and use it in GitHub Desktop.
Creating custom Error classes in Node.js
'use strict';
module.exports = function CustomError(message, extra) {
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message;
this.extra = extra;
};
require('util').inherits(module.exports, Error);

It's nice to be able to distinguish error types by classes. But it's a bit tricky to correctly create a custom error class in Node.js, so here is an example.

The example also shows how to add an extra parameter called extra that will be stored as a property on the error.

Usage

var CustomError = require('./errors/custom-error');

function doSomethingBad() {
  throw new CustomError('It went bad!', 42);
}

Features

  • Name appears once - less editing if you have to create lots of custom error classes
  • Easy to subclass - just change the last line to inherit from another custom error class you created
  • Correct stack trace - no extra stack frames, no double capturing of the stack trace

Anti-patterns

These are some things that I've seen in other proposed solutions that you should avoid.

  • Error.call(this) - creates another error object (wasting a bunch of time) and doesn't touch this at all
  • Error.captureStackTrace(this, arguments.callee); - works, but arguments.callee is deprecated, so don't use it
  • this.stack = (new Error).stack - this... I don't even...
// Mini test suite for our custom error
var assert = require('assert');
var CustomError = require('./errors/custom-error');
function doSomethingBad() {
throw new CustomError('It went bad!', 42);
}
try {
doSomethingBad();
} catch (err) {
// The name property should be set to the error's name
assert(err.name === 'CustomError');
// The error should be an instance of its class
assert(err instanceof CustomError);
// The error should be an instance of builtin Error
assert(err instanceof Error);
// The error should be recognized by Node.js' util#isError
assert(require('util').isError(err));
// The error should have recorded a stack
assert(err.stack);
// #toString should return the default error message formatting
assert.strictEqual(err.toString(), 'CustomError: It went bad!');
// The stack should start with the default error message formatting
assert.strictEqual(err.stack.split('\n')[0], 'CustomError: It went bad!');
// The first stack frame should be the function where the error was thrown
assert.strictEqual(err.stack.split('\n')[1].indexOf('doSomethingBad'), 7);
// The extra property should have been set
assert.strictEqual(err.extra, 42);
}
// Spoiler: It passes!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment