Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: release 3.23.2 caused change of exception messages due to non-Error exception serialiser #1260

Closed
zivl opened this issue Mar 15, 2018 · 3 comments

Comments

@zivl
Copy link
Contributor

zivl commented Mar 15, 2018

in release 3.23.2, the new feature "Sensible non-Error exception serializer" (#1253) causing errors which are made with es6-error (https://www.npmjs.com/package/es6-error) to change the error content.
it is being change in captureException function in this line:

options = this._getCaptureExceptionOptionsFromPlainObject(options, ex);

to be more specific, here is my code:

import ExtendableError from 'es6-error'

class CustomError extends ExtendableError {
  constructor(code, message) {
    super(message)
    this.name ='CustomError'
    this.code = code
  }
}

export default CustomError

then in the code:

Raven.captureException(new CustomError('code123', 'not working'));

// this will cause the error message to be "Non-Error exception captured with keys: code"
@kamilogorek
Copy link
Contributor

That seems to be a very strange behavior of JS modules.

When you use:

import ExtendableError from 'es6-error'

class CustomError extends ExtendableError {
  constructor(code, message) {
    super(message)
    this.name ='CustomError'
    this.code = code
  }
}

function isPlainObject(what) {
  return Object.prototype.toString.call(what) === '[object Object]';
}

function isError(value) {
  switch ({}.toString.call(value)) {
    case '[object Error]':
      return true;
    case '[object Exception]':
      return true;
    case '[object DOMException]':
      return true;
    default:
      return value instanceof Error;
  }
}

function isErrorEvent(value) {
  return Object.prototype.toString.call(value) === '[object ErrorEvent]';
}

var ex = new CustomError('code123', 'not working');

console.log('isPlainObject:', isPlainObject(ex))
console.log('isError:', isError(ex))
console.log('isErrorEvent:', isErrorEvent(ex))

It'll incorrectly report true/true/false.

However, when you'll substitute import statement with the code itself

class ExtendableError extends Error {
  constructor(message = '') {
    super(message);

    // extending Error is weird and does not propagate `message`
    Object.defineProperty(this, 'message', {
      configurable: true,
      enumerable : false,
      value : message,
      writable : true,
    });

    Object.defineProperty(this, 'name', {
      configurable: true,
      enumerable : false,
      value : this.constructor.name,
      writable : true,
    });

    if (Error.hasOwnProperty('captureStackTrace')) {
      Error.captureStackTrace(this, this.constructor);
      return;
    }

    Object.defineProperty(this, 'stack', {
      configurable: true,
      enumerable : false,
      value : (new Error(message)).stack,
      writable : true,
    });
  }
}

it'll correctly report false/true/false.

I'll try to debug why it's the case and if I won't be able to find out, we'll just swap checks to go through isError first.

@kamilogorek
Copy link
Contributor

@zivl When you test it locally, and create your own custom-error.js file with that code and import it as a module, it works correctly.

The issue is that this library doesn't export it's code "as is", but precompiles it using Babel.

Sooo it ends up being "kinda" error but not really. It's a plain object that inherits specific properties and has a prototype set to the Error itself.

There's no way around this unfortunately other than changing check order, as it's like a "schrodinger error". It is and is not an Error at the same time.

@kamilogorek
Copy link
Contributor

@zivl released in 3.23.3. Thanks for the report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants