[javascript] How do I create a custom Error in JavaScript?

For some reason it looks like constructor delegation doesn't work in the following snippet:

function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")

Running this gives The message is: ''. Any ideas as to why, or if there is a better way to create a new Error subclass? Is there a problem with applying to the native Error constructor that I don't know about?

This question is related to javascript exception

The answer is


In ES2015, you can use class to do this cleanly:

class NotImplemented extends Error {
  constructor(message = "", ...args) {
    super(message, ...args);
    this.message = message + " has not yet been implemented.";
  }
}

This does not modify the global Error prototype, allows you to customize message, name, and other attributes, and properly captures the stack. It's also pretty readable.

Of course, you may need to use a tool like babel if your code will be running on older browsers.


Accoring to Joyent you shouldn’t mess with the stack property (which I see in lots of answers given here), because it will have a negative impact on performance. Here is what they say:

stack: generally, don't mess with this. Don't even augment it. V8 only computes it if someone actually reads the property, which improves performance dramatically for handlable errors. If you read the property just to augment it, you'll end up paying the cost even if your caller doesn't need the stack.

I like and would like to mention their idea of wrapping the original error which is a nice replacement for passing on the stack.

So here is how I create a custom error, considering the above mentioned:

es5 version:

_x000D_
_x000D_
function RError(options) {_x000D_
    options = options || {}; // eslint-disable-line no-param-reassign_x000D_
    this.name = options.name;_x000D_
    this.message = options.message;_x000D_
    this.cause = options.cause;_x000D_
_x000D_
    // capture stack (this property is supposed to be treated as private)_x000D_
    this._err = new Error();_x000D_
_x000D_
    // create an iterable chain_x000D_
    this.chain = this.cause ? [this].concat(this.cause.chain) : [this];_x000D_
}_x000D_
RError.prototype = Object.create(Error.prototype, {_x000D_
    constructor: {_x000D_
        value: RError,_x000D_
        writable: true,_x000D_
        configurable: true_x000D_
    }_x000D_
});_x000D_
_x000D_
Object.defineProperty(RError.prototype, 'stack', {_x000D_
    get: function stack() {_x000D_
        return this.name + ': ' + this.message + '\n' + this._err.stack.split('\n').slice(2).join('\n');_x000D_
    }_x000D_
});_x000D_
_x000D_
Object.defineProperty(RError.prototype, 'why', {_x000D_
    get: function why() {_x000D_
        var _why = this.name + ': ' + this.message;_x000D_
        for (var i = 1; i < this.chain.length; i++) {_x000D_
            var e = this.chain[i];_x000D_
            _why += ' <- ' + e.name + ': ' + e.message;_x000D_
        }_x000D_
        return _why;_x000D_
    }_x000D_
});_x000D_
_x000D_
// usage_x000D_
_x000D_
function fail() {_x000D_
    throw new RError({_x000D_
        name: 'BAR',_x000D_
        message: 'I messed up.'_x000D_
    });_x000D_
}_x000D_
_x000D_
function failFurther() {_x000D_
    try {_x000D_
        fail();_x000D_
    } catch (err) {_x000D_
        throw new RError({_x000D_
            name: 'FOO',_x000D_
            message: 'Something went wrong.',_x000D_
            cause: err_x000D_
        });_x000D_
    }_x000D_
}_x000D_
_x000D_
try {_x000D_
    failFurther();_x000D_
} catch (err) {_x000D_
    console.error(err.why);_x000D_
    console.error(err.stack);_x000D_
    console.error(err.cause.stack);_x000D_
}
_x000D_
_x000D_
_x000D_

es6 version:

_x000D_
_x000D_
class RError extends Error {_x000D_
    constructor({name, message, cause}) {_x000D_
        super();_x000D_
        this.name = name;_x000D_
        this.message = message;_x000D_
        this.cause = cause;_x000D_
    }_x000D_
    [Symbol.iterator]() {_x000D_
        let current = this;_x000D_
        let done = false;_x000D_
        const iterator = {_x000D_
            next() {_x000D_
                const val = current;_x000D_
                if (done) {_x000D_
                    return { value: val, done: true };_x000D_
                }_x000D_
                current = current.cause;_x000D_
                if (!val.cause) {_x000D_
                    done = true;_x000D_
                }_x000D_
                return { value: val, done: false };_x000D_
            }_x000D_
        };_x000D_
        return iterator;_x000D_
    }_x000D_
    get why() {_x000D_
        let _why = '';_x000D_
        for (const e of this) {_x000D_
            _why += `${_why.length ? ' <- ' : ''}${e.name}: ${e.message}`;_x000D_
        }_x000D_
        return _why;_x000D_
    }_x000D_
}_x000D_
_x000D_
// usage_x000D_
_x000D_
function fail() {_x000D_
    throw new RError({_x000D_
        name: 'BAR',_x000D_
        message: 'I messed up.'_x000D_
    });_x000D_
}_x000D_
_x000D_
function failFurther() {_x000D_
    try {_x000D_
        fail();_x000D_
    } catch (err) {_x000D_
        throw new RError({_x000D_
            name: 'FOO',_x000D_
            message: 'Something went wrong.',_x000D_
            cause: err_x000D_
        });_x000D_
    }_x000D_
}_x000D_
_x000D_
try {_x000D_
    failFurther();_x000D_
} catch (err) {_x000D_
    console.error(err.why);_x000D_
    console.error(err.stack);_x000D_
    console.error(err.cause.stack);_x000D_
}
_x000D_
_x000D_
_x000D_

I’ve put my solution into a module, here it is: https://www.npmjs.com/package/rerror


This section of the standard may explain why the Error.apply call doesn't initialize the object:

15.11.1 The Error Constructor Called as a Function

When Error is called as a function rather than as a constructor, it creates and initialises a new Error object. Thus the function call Error(...) is equivalent to the object creation expression new Error(...) with the same arguments.

In this case the Error function probably determines that it's not being called as a constructor, so it returns a new Error instance rather than initializing the this object.

Testing with the following code seems to demonstrate that this is in fact what's happening:

function NotImplementedError() { 
   var returned = Error.apply(this, arguments);
   console.log("returned.message = '" + returned.message + "'");
   console.log("this.message = '" + this.message + "'");
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");

The following output is generated when this is run:

returned.message = 'some message'
this.message = ''

This is fastest way to do it:

    let thisVar = false

    if (thisVar === false) {
            throw new Error("thisVar is false. It should be true.")
    }

This is implemented nicely in the Cesium DeveloperError:

In it's simplified form:

var NotImplementedError = function(message) {
    this.name = 'NotImplementedError';
    this.message = message;
    this.stack = (new Error()).stack;
}

// Later on...

throw new NotImplementedError();

Try a new prototype object for each instance of the user defined error type. It allows instanceof checks to behave as usual plus type and message are correctly reported in Firefox and V8 (Chome, nodejs).

function NotImplementedError(message){
    if(NotImplementedError.innercall===undefined){
        NotImplementedError.innercall = true;
        NotImplementedError.prototype = new Error(message);
        NotImplementedError.prototype.name = "NotImplementedError";
        NotImplementedError.prototype.constructor = NotImplementedError;

        return new NotImplementedError(message);
    }
    delete NotImplementedError.innercall;
}

Note that an additional entry will preceed the otherwise correct stack.


If you are using Node/Chrome. The following snippet will get you extension which meets the following requirements.

  • err instanceof Error
  • err instanceof CustomErrorType
  • console.log() returns [CustomErrorType] when created with a message
  • console.log() returns [CustomErrorType: message] when created without a message
  • throw/stack provides the information at the point the error was created.
  • Works optimally in Node.JS, and Chrome.
  • Will pass instanceof checks in Chrome, Safari, Firefox and IE 8+, but will not have a valid stack outside of Chrome/Safari. I'm OK with that because I can debug in chrome, but code which requires specific error types will still function cross browser. If you need Node only you can easily remove the if statements and you're good to go.

Snippet

var CustomErrorType = function(message) {
    if (Object.defineProperty) {
        Object.defineProperty(this, "message", {
            value : message || "",
            enumerable : false
        });
    } else {
        this.message = message;
    }

    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, CustomErrorType);
    }
}

CustomErrorType.prototype = new Error();
CustomErrorType.prototype.name = "CustomErrorType";

Usage

var err = new CustomErrorType("foo");

Output

var err = new CustomErrorType("foo");
console.log(err);
console.log(err.stack);

[CustomErrorType: foo]
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

/errorTest.js:30
        throw err;
              ^
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

At the expense of not being able to use instanceof, the following preserves the original stack trace and doesn't use any non-standard tricks.

// the function itself
var fixError = function(err, name) {
    err.name = name;
    return err;
}

// using the function
try {
    throw fixError(new Error('custom error message'), 'CustomError');
} catch (e) {
    if (e.name == 'CustomError')
        console.log('Wee! Custom Error! Msg:', e.message);
    else
        throw e; // unhandled. let it propagate upwards the call stack
}

class NotImplementedError extends Error {
  constructor(message) {
    super(message);
    this.message = message;
  }
}
NotImplementedError.prototype.name = 'NotImplementedError';
module.exports = NotImplementedError;

and

try {
  var e = new NotImplementedError("NotImplementedError message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

It is just a class representation of this answer.

output

NotImplementedError: NotImplementedError message
  ...stacktrace
ex1 instanceof NotImplementedError = true
ex1 instanceof Error = true
ex1.name = NotImplementedError
ex1.message = NotImplementedError message

I like to do it like this:

  • Make use of name so toString() throws "{code}: {message}"
  • Return same thing to super so it appears the same in the stacktrace
  • Attach code to error.code as checking/parsing a code is better in code than checking a message, which you might want to localize for example
  • Attach message to error.message as an alternative to error.toString()

_x000D_
_x000D_
class AppException extends Error {_x000D_
  constructor(code, message) {_x000D_
    const fullMsg = message ? `${code}: ${message}` : code;_x000D_
    super(fullMsg);_x000D_
    this.name = code;_x000D_
    this.code = code;_x000D_
    this.message = fullMsg;_x000D_
  }_x000D_
  _x000D_
  toString() {_x000D_
    return this.message;_x000D_
  }_x000D_
}_x000D_
_x000D_
// Just a code_x000D_
try {_x000D_
  throw new AppException('FORBIDDEN');_x000D_
} catch(e) {_x000D_
  console.error(e);_x000D_
  console.error(e.toString());_x000D_
  console.log(e.code === 'FORBIDDEN');_x000D_
}_x000D_
_x000D_
// A code and a message_x000D_
try {_x000D_
  throw new AppException('FORBIDDEN', 'You don\'t have access to this page');_x000D_
} catch(e) {_x000D_
  console.error(e);_x000D_
  console.error(e.toString());_x000D_
  console.log(e.code === 'FORBIDDEN');_x000D_
}
_x000D_
_x000D_
_x000D_


The following worked for me taken from the official Mozilla documentation Error.

function NotImplementedError(message) {
    var instance = new Error(message);
    instance.name = 'NotImplementedError';

    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    if (Error.captureStackTrace) {
        Error.captureStackTrace(instance, NotImplementedError);
    }
    return instance;
}

NotImplementedError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
    }
});

The constructor needs to be like a factory method and return what you want. If you need additional methods/properties, you can add them to the object before returning it.

function NotImplementedError(message) { return new Error("Not implemented", message); }

x = new NotImplementedError();

Though I'm not sure why you'd need to do this. Why not just use new Error... ? Custom exceptions don't really add much in JavaScript (or probably any untyped language).


Another alternative , might not work in all enviroments.Atleast assured it works in nodejs 0.8 This approach uses a non standard way of modifying the internal proto prop

function myError(msg){ 
      var e = new Error(msg); 
      _this = this; 
      _this.__proto__.__proto__ = e;
}

I just had to implement something like this and found that the stack was lost in my own error implementation. What I had to do was create a dummy error and retrieve the stack from that:

My.Error = function (message, innerException) {
    var err = new Error();
    this.stack = err.stack; // IMPORTANT!
    this.name = "Error";
    this.message = message;
    this.innerException = innerException;
}
My.Error.prototype = new Error();
My.Error.prototype.constructor = My.Error;
My.Error.prototype.toString = function (includeStackTrace) {
    var msg = this.message;
    var e = this.innerException;
    while (e) {
        msg += " The details are:\n" + e.message;
        e = e.innerException;
    }
    if (includeStackTrace) {
        msg += "\n\nStack Trace:\n\n" + this.stack;
    }
    return msg;
}

This is my implementation:

class HttpError extends Error {
  constructor(message, code = null, status = null, stack = null, name = null) {
    super();
    this.message = message;
    this.status = 500;

    this.name = name || this.constructor.name;
    this.code = code || `E_${this.name.toUpperCase()}`;
    this.stack = stack || null;
  }

  static fromObject(error) {
    if (error instanceof HttpError) {
      return error;
    }
    else {
      const { message, code, status, stack } = error;
      return new ServerError(message, code, status, stack, error.constructor.name);
    }
  }

  expose() {
    if (this instanceof ClientError) {
      return { ...this };
    }
    else {
      return {
        name: this.name,
        code: this.code,
        status: this.status,
      }
    }
  }
}

class ServerError extends HttpError {}

class ClientError extends HttpError { }

class IncorrectCredentials extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 400;
  }
}

class ResourceNotFound extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 404;
  }
}

Example usage #1:

app.use((req, res, next) => {
  try {
    invalidFunction();
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

Example usage #2:

router.post('/api/auth', async (req, res) => {
  try {
    const isLogged = await User.logIn(req.body.username, req.body.password);

    if (!isLogged) {
      throw new IncorrectCredentials('Incorrect username or password');
    }
    else {
      return res.status(200).send({
        token,
      });
    }
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

If anyone is curious on how to create a custom error and get the stack trace:

function CustomError(message) {
  this.name = 'CustomError';
  this.message = message || '';
  var error = new Error(this.message);
  error.name = this.name;
  this.stack = error.stack;
}
CustomError.prototype = Object.create(Error.prototype);

try {
  throw new CustomError('foobar');
}
catch (e) {
  console.log('name:', e.name);
  console.log('message:', e.message);
  console.log('stack:', e.stack);
}

easier way. You could make your object inherit from the Error object. Example:

function NotImplementError(message)
{
    this.message = message;
    Error.call();
    Error.call(message);
} 

what we are doing is using the function call() which call the constructor of the Error class so is basicly the same thing as implementing a class inheritance in other object oriented languages.


All of the above answers are terrible awful - really. Even the one with 107 ups! The real answer is here guys:

Inheriting from the Error object - where is the message property?

TL;DR:

A. The reason message isn't being set is that Error is a function that returns a new Error object and does not manipulate this in any way.

B. The way to do this right is to return the result of the apply from the constructor, as well as setting the prototype in the usual complicated javascripty way:

_x000D_
_x000D_
function MyError() {_x000D_
    var temp = Error.apply(this, arguments);_x000D_
    temp.name = this.name = 'MyError';_x000D_
    this.message = temp.message;_x000D_
    if(Object.defineProperty) {_x000D_
        // getter for more optimizy goodness_x000D_
        /*this.stack = */Object.defineProperty(this, 'stack', { _x000D_
            get: function() {_x000D_
                return temp.stack_x000D_
            },_x000D_
            configurable: true // so you can change it if you want_x000D_
        })_x000D_
    } else {_x000D_
        this.stack = temp.stack_x000D_
    }_x000D_
}_x000D_
//inherit prototype using ECMAScript 5 (IE 9+)_x000D_
MyError.prototype = Object.create(Error.prototype, {_x000D_
    constructor: {_x000D_
        value: MyError,_x000D_
        writable: true,_x000D_
        configurable: true_x000D_
    }_x000D_
});_x000D_
_x000D_
var myError = new MyError("message");_x000D_
console.log("The message is: '" + myError.message + "'"); // The message is: 'message'_x000D_
console.log(myError instanceof Error); // true_x000D_
console.log(myError instanceof MyError); // true_x000D_
console.log(myError.toString()); // MyError: message_x000D_
console.log(myError.stack); // MyError: message \n _x000D_
// <stack trace ...>_x000D_
_x000D_
_x000D_
 _x000D_
//for EMCAScript 4 or ealier (IE 8 or ealier), inherit prototype this way instead of above code:_x000D_
/*_x000D_
var IntermediateInheritor = function() {};_x000D_
IntermediateInheritor.prototype = Error.prototype;_x000D_
MyError.prototype = new IntermediateInheritor();_x000D_
*/
_x000D_
_x000D_
_x000D_

You could probably do some trickery to enumerate through all the non-enumerable properties of the tmp Error to set them rather than explicitly setting only stack and message, but the trickery isn't supported in ie<9


function InvalidValueError(value, type) {
    this.message = "Expected `" + type.name + "`: " + value;
    var error = new Error(this.message);
    this.stack = error.stack;
}
InvalidValueError.prototype = new Error();
InvalidValueError.prototype.name = InvalidValueError.name;
InvalidValueError.prototype.constructor = InvalidValueError;

I used the Constructor Pattern to create the new error object. I defined the prototype chain such as an Error instance. See the MDN Error constructor reference.

You can check this snippet on this gist.

IMPLEMENTATION

// Creates user-defined exceptions
var CustomError = (function() {
  'use strict';

  //constructor
  function CustomError() {
    //enforces 'new' instance
    if (!(this instanceof CustomError)) {
      return new CustomError(arguments);
    }
    var error,
      //handles the arguments object when is passed by enforcing a 'new' instance
      args = Array.apply(null, typeof arguments[0] === 'object' ? arguments[0] : arguments),
      message = args.shift() || 'An exception has occurred';

    //builds the message with multiple arguments
    if (~message.indexOf('}')) {
      args.forEach(function(arg, i) {
        message = message.replace(RegExp('\\{' + i + '}', 'g'), arg);
      });
    }

    //gets the exception stack
    error = new Error(message);
    //access to CustomError.prototype.name
    error.name = this.name;

    //set the properties of the instance
    //in order to resemble an Error instance
    Object.defineProperties(this, {
      stack: {
        enumerable: false,
        get: function() { return error.stack; }
      },
      message: {
        enumerable: false,
        value: message
      }
    });
  }

  // Creates the prototype and prevents the direct reference to Error.prototype;
  // Not used new Error() here because an exception would be raised here,
  // but we need to raise the exception when CustomError instance is created.
  CustomError.prototype = Object.create(Error.prototype, {
    //fixes the link to the constructor (ES5)
    constructor: setDescriptor(CustomError),
    name: setDescriptor('JSU Error')
  });

  function setDescriptor(value) {
    return {
      configurable: false,
      enumerable: false,
      writable: false,
      value: value
    };
  }

  //returns the constructor
  return CustomError;
}());

USAGE

The CustomError constructor can receive many arguments to build the message, e.g.

var err1 = new CustomError("The url of file is required"),
    err2 = new CustomError("Invalid Date: {0}", +"date"),
    err3 = new CustomError("The length must be greater than {0}", 4),
    err4 = new CustomError("Properties .{0} and .{1} don't exist", "p1", "p2");

throw err4;

And this is how the custom error looks:

Custom error prototype chain


I had a similar issue to this. My error needs to be an instanceof both Error and NotImplemented, and it also needs to produce a coherent backtrace in the console.

My solution:

var NotImplemented = (function() {
  var NotImplemented, err;
  NotImplemented = (function() {
    function NotImplemented(message) {
      var err;
      err = new Error(message);
      err.name = "NotImplemented";
      this.message = err.message;
      if (err.stack) this.stack = err.stack;
    }
    return NotImplemented;
  })();
  err = new Error();
  err.name = "NotImplemented";
  NotImplemented.prototype = err;

  return NotImplemented;
}).call(this);

// TEST:
console.log("instanceof Error: " + (new NotImplemented() instanceof Error));
console.log("instanceof NotImplemented: " + (new NotImplemented() instanceofNotImplemented));
console.log("message: "+(new NotImplemented('I was too busy').message));
throw new NotImplemented("just didn't feel like it");

Result of running with node.js:

instanceof Error: true
instanceof NotImplemented: true
message: I was too busy

/private/tmp/t.js:24
throw new NotImplemented("just didn't feel like it");
      ^
NotImplemented: just didn't feel like it
    at Error.NotImplemented (/Users/colin/projects/gems/jax/t.js:6:13)
    at Object.<anonymous> (/Users/colin/projects/gems/jax/t.js:24:7)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:487:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

The error passes all 3 of my criteria, and although the stack property is nonstandard, it is supported in most newer browsers which is acceptable in my case.


MDN has an excellent example:

try {
  throw new Error('Whoops!');
} catch (e) {
  console.log(e.name + ': ' + e.message);
}