diff --git a/src/server/rollbar.js b/src/server/rollbar.js index 55af8e1b2..947e8c385 100644 --- a/src/server/rollbar.js +++ b/src/server/rollbar.js @@ -280,7 +280,7 @@ Rollbar.prototype.errorHandler = function () { return next(err, request, response); } - if (err instanceof Error) { + if (_.isError(err)) { return this.error(err, request, cb); } return this.error('Error: ' + err, request, cb); diff --git a/src/utility.js b/src/utility.js index e64057cbb..0850bdd0f 100644 --- a/src/utility.js +++ b/src/utility.js @@ -139,8 +139,10 @@ function isIterable(i) { * @returns true if e is an error */ function isError(e) { - // Detect both Error and Firefox Exception type - return isType(e, 'error') || isType(e, 'exception'); + // Detect Error, Firefox Exception type and error like object + return (isType(e, 'error') + || isType(e, 'exception') + || (typeof e === 'object' && e && e.name && e.message)); } function redact() { @@ -410,7 +412,7 @@ function createItem(args, logger, notifier, requestKeys, lambdaContext) { break; case 'object': case 'array': - if (arg instanceof Error || (typeof DOMException !== 'undefined' && arg instanceof DOMException)) { + if (isError(arg)) { err ? extraArgs.push(arg) : err = arg; break; } @@ -428,7 +430,7 @@ function createItem(args, logger, notifier, requestKeys, lambdaContext) { custom ? extraArgs.push(arg) : custom = arg; break; default: - if (arg instanceof Error || (typeof DOMException !== 'undefined' && arg instanceof DOMException)) { + if (isError(arg)) { err ? extraArgs.push(arg) : err = arg; break; } diff --git a/test/utility.test.js b/test/utility.test.js index 2e7158efd..e839876e8 100644 --- a/test/utility.test.js +++ b/test/utility.test.js @@ -244,6 +244,38 @@ describe('isError', function() { expect(_.isError(e)).to.be.ok(); done(); }); + it('should handle classes implementing the error interface', function(done) { + // This is a mostly browser compliant way of doing this + // just for the sake of doing it, even though we mostly + // need this to work in node environments + function TestCustomError(message) { + Object.defineProperty(this, 'name', { + enumerable: false, + writable: false, + value: 'TestCustomError' + }); + + Object.defineProperty(this, 'message', { + enumerable: false, + writable: true, + value: message + }); + + if (Error.hasOwnProperty('captureStackTrace')) { + Error.captureStackTrace(this, TestCustomError); + } else { + Object.defineProperty(this, 'stack', { + enumerable: false, + writable: false, + value: (new Error(message)).stack + }); + } + } + + var e = new TestCustomError('bork'); + expect(_.isError(e)).to.be.ok(); + done(); + }); }); describe('merge', function() {