Sentry-react-native: Non-Error exception captured with keys: error

Created on 20 Apr 2018  Ā·  44Comments  Ā·  Source: getsentry/sentry-react-native

OS:

  • [ ] Windows
  • [x] MacOS
  • [ ] Linux

_Platform:_

  • [ ] iOS
  • [x] Android

Output of node -v && npm -v && npm ls --prod --depth=0

v9.7.1
5.7.1

Config:

Sentry.config('https://[email protected]/...', {
....
}).install()
"react": "16.2.0",
"react-native": "0.53.0",

"react-native-sentry": "^0.35.3",

I am getting lots of crashes with this error -

 } else if (isPlainObject(ex)) {
      // If it is plain Object, serialize it manually and extract options
      // This will allow us to group events based on top-level keys
      // which is much better than creating new group when any key/value change
      options = this._getCaptureExceptionOptionsFromPlainObject(options, ex);
      ex = new Error(options.message);
    } else {
      // If none of previous checks were valid, then it means that
      // it's not a plain Object
      // it's not a valid ErrorEvent (one with an error property)
      // it's not an Error

Most helpful comment

This is not specific to react-native, i got this on angular 6 application

All 44 comments

šŸ‘ Same here

Can you link a Sentry event here please?

Attached a screen shot.

screen shot 2018-04-24 at 9 55 32 am

The next release (which is currently building) should fix this.
Stay tuned for 0.36.0.

Still got this error:
Non-Error exception captured with keys: error, headers, message, name, ok…

Same here; got mine originating from https://github.com/react-native-community/react-native-share/blob/71737360313e35216062036c8a60416dc2aefc80/index.js#L182 and captured it with

try {
  // my code
} catch (e) {
  Sentry.captureException(e);
}

Am I capturing this the wrong way?

@HazAT Here is a link for a similar error ("_Error: Non-Error exception captured with keys: errorCode, errorMessage…_"):

https://sentry.io/share/issue/1d9a134305c747f6a134880e134e51d5/

Also still getting this for an angular6 frontend:

Non-Error exception captured with keys: error, headers, message, name, ok…

EDIT: Sorry - didn't realize this was specific to react-native-sentry

This is not specific to react-native, i got this on angular 6 application

@glebmachine Yep, agreed - just this issue is in the react-native-sentry repo

Hello, I have the same issue with an angular 6 app, my Raven-js version is 3.26.3 and my sentry version 9.0.0

Any updates on this? Happening on angular6 with raven-js 3.26.4.

Happening on vue2 with "raven-js": "^3.26.4"

hey,I found the reason in my project,It doesn't matter with the version or framwork.
The correct format to throw the error is throw new Error(err.data.message), not throw new Error(err)
Which means that the error should be a String

After I modified this, this error has never happened again.
hope this helps

@lilywang711 I would like to disagree, the error can be an Error, ErrorEvent or string.
While only setting a string may work for you, it is not a solution for everybody.

Happens on Reactjs web app too

same here

So, if this has occurred, it means that Sentry/Raven doesn't believe the error is an Error but rather some other object. And we iterate through the keys to give you a clue what we caught instead.

Note that if you're trying to capture a custom Error (e.g. a subclass, whether defined by your code or the framework code), there's a specific way to do this to make sure it also is detectable as an Error. You can verify it works by verifying MyError instanceof Error evaluates to true.

For example, @jackrvaughan wrote:

Non-Error exception captured with keys: error, headers, message, name, ok…

This means that Sentry/Raven encountered a JavaScript object with this shape:

{
  error: { ... /* some genuine error object probably? */ ... },
  headers: { ... /* some sub-object probably? */ },
  message: '???',
  name: '???',
  ...
}

(That doesn't look like an Error proper to me.)

on Node v10.7.0 using "@sentry/node": "^4.0.3" I got this on my code (Custom error)

class AppError extends Error {
    constructor(error) {
        super(error.err_msg);
        this.name = this.constructor.name;
        Error.captureStackTrace(this, this.constructor);
    }
}

then throw

const a =  new AppError({ err_msg: "test d" })
console.log(a instanceof Error) // true
throw a

and I get:

[email protected]:backend in NodeBackend.<anonymous>
errorNon-Error exception captured with keys: name

I tried this solution https://github.com/getsentry/sentry-javascript/issues/1260#issuecomment-373398920 but still getting something like:

errorNon-Error exception captured with keys: [object has no keys]

I'm not able to reproduce this issue locally.

Test code:

const Sentry = require("@sentry/node");

Sentry.init({
  dsn: "http://[email protected]/42",
  beforeSend(event) {
    console.log(JSON.stringify(event, null, 2));
    return null;
  }
});

class AppError extends Error {
  constructor(error) {
    super(error.err_msg);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

throw new AppError({ err_msg: "test d" });

I also tried direct captureException instead of a throw

Sentry.captureException(new AppError({ err_msg: "test d" }));

and it worked just fine as well.

Logs:

{
  "exception": {
    "values": [
      {
        "stacktrace": {
          "frames": [// removed to not take too much space]
        },
        "type": "AppError",
        "value": "test d"
      }
    ]
  },
  "message": "AppError: test d",
  "extra": {
    "AppError": {
      "name": "AppError"
    }
  },
  // rest of the event
}

Tested on @sentry/[email protected] (latest) as well as on mentioned @sentry/[email protected].
And node versions 8.11.1, 10.7.0 and 10.11.0 (latest). All tests with the same results.

happened on vue2.6 with "raven-js 3.27.0"

We're getting these errors in our Ionic application with raven.js 3.26.4

@richardshergold if you're able to reproduce it locally, use

init({
  dsn: 'your_dsn',
  beforeSend(event, hint) {
    console.log(hint.originalException);
    return event;
  }
})

to investigate what's the shape of the error and update it appropriately.

@kamilogorek thanks - I haven't been able to produce locally actually If I added that code in Production though presumably I would see that info in the console breadcrumbs?

I would see that info in the console breadcrumbs?

No, we are excluding logging from our own callbacks, otherwise, it could create an infinite loop.

You can do something like:

Sentry.init({
  dsn: 'your_dsn',
  beforeSend(event, hint) {
    if (event.message.startsWith('Non-Error exception captured') && hint.originalException.error) {
      Sentry.withScope((scope) => {
        scope.setExtra('nonErrorException', true);
        Sentry.captureException(hint.originalException.error);
      });
      return null;
    }
    return event;
  }
})

This'll prevent those errors from being sent to Sentry and will catch originalException.error instead.
You can do any filtering/modifications in beforeSend or even better, an event processor. https://docs.sentry.io/platforms/javascript/#eventprocessors

@kamilogorek I have those TypeScript errors with the above code:

Property 'setExtra' does not exist on type 'typeof import(_sentry browser node module path_)

And

Property 'error' does not exist on type 'Error'.

Any idea?

@Riccardo-Andreatta yeh, my example had a bug šŸ˜… It should be scope.setExtra, not Sentry.setExtra.
Regarding first error, it's because we assume originalException is an Error object, but in case of this thread, it's a non-standard one (there's no Error.error in the native implementation).

interface ExtendedError extends Error {
  error: Error; // or `any`
}

and then

if (!hint.originalException) return event;

const customError = (hint.originalException as ExtendedError).error;

if (event.message.startsWith('Non-Error exception captured') && customError) {
  Sentry.withScope((scope) => {
    scope.setExtra('nonErrorException', true);
    Sentry.captureException(customError);
  });
  return null;
}

@kamilogorek just looking at this again - we are using Raven.js - can these events be filtered out in the same way using Raven i.e with something like the BeforeSend option you provided above?

@richardshergold you can filter them out (there's dataCallback method), but you wont have an access to the original exceptiion in case you'd like to override it.

@kamilogorek ok thank you. Just so I am understanding (I am in the process of deciding whether or not to move from using raven.js to the Cordova plugin and the new SDK - ours is an Ionic app) - why, with Raven, won't I have access to the original exception? (and would this be a good reason to move from raven.js?)

There's no mechanism that passes original instance that was used to create a Sentry event. Only new v4 SDK has this feature. They are called hints https://docs.sentry.io/platforms/javascript/#hints
Yes, it's one of the reasons why some people move to the new version.

@kamilogorek @HazAT I'm having this issue in react-native-sentry. How can I do the beforeSend trick @kamilogorek suggested? I do not see beforeSend at https://docs.sentry.io/clients/react-native/config/ (even though it's mentioned in JS, https://docs.sentry.io/platforms/javascript/?platform=node#eventprocessors )?

My error is Non-Error exception captured with keys: error, meta, payload, type (when I click on the blue + symbol in below, I only see "")
image

@cihati this is exactly what you should see, as we are trying to provide any usable information that can be used to find out where is the cause :)

In this case, you somewhere do throw obj where obj is the thing from the log above.

react-native-sentry doesn't have beforeSend with the hint, but setDataCallback instead as it's not part of our core sentry-javascript SDK yet.

Sentry.setDataCallback((event) => {
  // you can inspect and override the event here as described in the comments above
  return event;
});

Received the following error Non-Error exception captured with keys: message, status

@valerii-cognite then you have throw { message: '', status: '' } somewhere in your code, where the only thing you should throw is error instance

Was it fixed after 0.42.0?

I get the same problem on 0.42

My code:

try {
      active = await this.someMethod()
    } catch (error) {
      alert(error.message)
      Sentry.captureException(error)
      this.setState({
        isDongSomething: false
      })
    }

With this code I get Non-Error exception captured with keys: default in Sentry

@DataGreed not sure what's the status of react-native on this issue as I'm not working on it. However, new v1 uses @sentry/browser (this SDK) instead of old raven.js SDK, thus I assume it should be fixed – https://github.com/getsentry/sentry-react-native/releases

For Angular I having the same problem with this code. I find out that returning a new empty error instance produced this error:

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

  constructor() { }

  handleError(error: any) {

    if (environment.production) {
      Sentry.captureException(error.originalError || error);
    }

    return new ErrorHandler();
  }

}

So I fixed with this solution:

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

  constructor() { }

  handleError(error: any) {

    if (environment.production) {
      Sentry.captureException(error.originalError || error);
    } else {
      console.error(error);
    }

  }

}

i found this answer helpful from a related issue.

@romelgomez where to place this solution code in angular 8

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

constructor() { }

handleError(error: any) {

if (environment.production) {
  Sentry.captureException(error.originalError || error);
} else {
  console.error(error);
}

}

}

and one more question is :::

I think it is not necessary to console the error in production environment ...

Hi @himajaM , I think, what i can remember is:

e.g: https://sentry.io/for/angular/

Instead of using ErrorHandler class, I passed a new class SentryErrorHandler

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

  constructor() { }

  handleError(error: any) {

    if (environment.production) {
      Sentry.captureException(error.originalError || error);
    } else {
      console.error(error);
    }

  }

}

environment.production will be true in production and then the error will be registed in Sentry, other side (develoment )will be log in the console of developer and not in Sentry, this is for avoid send develoment errors to the Sentry API

Thanks for your response...

Is this the only way (i.e console.error(error)) to avoid logs in sentry?

and where can i inject SentryErrorHandler class in angular 8

On Mon, Dec 21, 2020 at 9:55 PM Romel Gomez notifications@github.com
wrote:

Hi @himajaM https://github.com/himajaM , I think, what i can remember
is:

e.g: https://sentry.io/for/angular/

Instead of using ErrorHandler class, I passed a new class
SentryErrorHandler

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

constructor() { }

handleError(error: any) {

if (environment.production) {
  Sentry.captureException(error.originalError || error);
} else {
  console.error(error);
}

}

}

environment.production will be true in production and then the error will
be registed in Sentry, other side (develoment )will be log in the console
of developer and not in Sentry, this is for avoid send develoment errors
saved in Sentry API

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/getsentry/sentry-react-native/issues/391#issuecomment-749060282,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AGHL5UIYQCQHXFPK7PW4IGLSV5ZJBANCNFSM4E3X2Y6Q
.

Was this page helpful?
0 / 5 - 0 ratings