I am using custom Error objects in node.js (0.8.12) with express (2.5.8). When errors occur, I want to route them to my custom error handler, but my custom Error objects are converted to Strings, while native Error objects stay the same.
Here is a simple example:
var express = require('express');
var APIError = function(type) {
this.type = type;
}
APIError.prototype = new Error();
var app = express.createServer();
app.use(app.router);
app.use(apiErrorHandler);
function log(source, err) {
console.log(
source,
typeof err,
err.constructor.name,
err instanceof APIError,
err instanceof Error
);
}
function apiErrorHandler(err, req, res, next) {
log("error handler:", err);
}
app.get('/', function(req, res, next) {
var err = new APIError("notAllowed");
log("router:", err);
next(err);
});
app.listen(80);
The console output from this example is the following:
router: object Error true true
error handler: string String false false
If I replace new APIError("notAllowed") with new Error("notAllowed"), the object is conserved and a request produces this output:
router: object Error false true
error handler: object Error false true
Why is my custom Error object converted, although it is an instance of Error?
Try this. Note that APIError is now a named function:
var util = require('util');
function APIError(type) {
Error.call(this, {
message: type,
constructorOpt: APIError
});
this.name = 'APIError';
}
util.inherits(APIError, Error);
APIError.prototype.name = 'APIError';
Also, have a look here.
In fact what's happening is that the string showing up is not your error object at all - it's another error being thrown inside the guts of Express (an "illegal access" exception). The error is happening when Express is comparing the error object to a string.
The root cause is apparently setting the "type" property on your custom Error object. This is apparently a no-no with V8 - it causes toString() to thrown the "illegal access" exception. More details here: https://code.google.com/p/v8/issues/detail?id=2397