Sentry-javascript: Event: Non-Error promise rejection captured with keys: currentTarget, isTrusted, target, type

Created on 20 Apr 2020  ·  21Comments  ·  Source: getsentry/sentry-javascript

Package + Version

  • [x] @sentry/browser
  • [ ] @sentry/node
  • [ ] raven-js
  • [ ] raven-node _(raven for node)_
  • [ ] other:

Version:

5.10.2

Description

My project often catch an error like Event Non-Error promise rejection captured with keys: currentTarget, isTrusted, target, type,without any useful information. And an additional data is

__serialized__ = {
    currentTarget: [object Null], 
    isTrusted: [Circular ~], 
    target: head > script[type="text/javascript"], 
    type: error
}

looks like an Event instance. With the limited information,I don't know where this bug is triggered,has anyone encountered the same problem?

Needs Information

Most helpful comment

This error just depleted my quota capacity.

All 21 comments

We've also started seeing these in the last couple of weeks. I just started looking into it so I don't have any more details on what's causing it.

Same here, now on Sentry v5.15.5.

Can someone provide any link to this type of event captured in Sentry? It looks like a script loading error (notice the target that this event has been triggered on)

@kamilogorek can you please send me your company email? I can share examples of the events.

If you need more examples I can send some over as well @kamilogorek -- just let me know.

@sheelah yes, please

@sheelah there's not much we can improve here, to be honest. JS doesn't give us more information that we already provide. Whenever an instance of a promise object is rejected, it triggers onunhandledrejection event (same goes for onerror in the OP description).

https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event

However, there's nothing that would stop anyone from passing any random stuff in there.
Thus code like this Promise.reject("whatever") or Promise.reject(jQueryBecauseWhyNot) is totally valid JS code.

Whenever we encounter something that's not a primitive value, an object that contains the stack trace (eg. Error) or internal DOM exception, we have to fall back to simple object serialization and try to extract whatever information we can out of it. You can see eventbuilder.ts file for a list of possible paths this "any random value" passed to the event handler can take – https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/eventbuilder.ts#L17-L80

Unfortunately, I'm not sure if we can make it any more generic to handle more types of input.
If anyone has any feedback regarding that process, I'm totally open to suggestions.

(answered here instead of to your email, to keep the conversation public for everyone else)

From my observations:

  • Only happens in various recent versions of Safari on mobile or desktop;
  • I have a few libraries installed in my web app such as ZXing and browser-image-compression, but no third-party tracking scripts;
  • It seems to occur at the exact same time as an API call fails with a Network Error (code 0).
  • In my case, it is more specifically a ProgressEvent, not just an event - which seems to be a part of HTTP request library (I am using axios).
ADDITIONAL DATA

__serialized__ | {
    currentTarget: [object Null],
    isTrusted: [Circular ~],
    target: [object FileReader],
    type: error}
-- | --

I also just received a report with "Non-Error promise rejection captured with value: null". Similar to what @anton-bot mentioned above the affected user was using Safari 13.1.2 on Mac OS X 10.15.6.

I had a look in my compiled app code for reject( calls where a possibly null object is provided, but couldn't find any, so I was wondering if it might be a browser extension or 3rd party script. Since there's no stack trace or breadcrumbs it's quite hard to know what exactly happened.

Have also been seeing this for the past two weeks. On our site we've only seen it on pages that use the google maps javascript API so I have a feeling that it might be related to that. Anyone else seeing this on URLs that use google maps?

Edit: So far we've seen the issue on iOS and Android

Edit: Additional data:

{
  currentTarget: [object Null], 
  isTrusted: [Circular ~], 
  target: head > script[type="text/javascript"], 
  type: error
}

@asbjornh nope I don't have Google Maps in my page

@kamilogorek Would OP's additional data (and mine) be caused by something like this Promise.reject(new Event("error"))? Or would Sentry events for this situation always have payloads that look like browser events?

I am also getting same error

This error just depleted my quota capacity.

we have 289 events of this in the last 24h - and our page is not even live yet ..

{
currentTarget: [object Null], 
isTrusted: [Circular ~], 
target: head > link, 
type: error
}

We are using next.js

same here with cra 😅

It seems that this issue is caused by something roughly like this:

new Promise((resolve, reject) => {
  const script = document.createElement('script');
  script.src = src;
  script.onload = resolve;
  script.onerror = reject;
  document.body.appendChild(script);
});

The onerror hook will actually receive an Event object, instead of an Error instance, which is causing these issues that are mentioned above. This can be avoided by wrapping the Event with an Error as suggested by https://developer.mozilla.org/de/docs/Web/API/HTMLScriptElement:

new Promise((resolve, reject) => {
  const script = document.createElement('script');
  script.src = src;
  script.onload = resolve;
  script.onerror = event => {
    reject(new Error(`Failed to load ${event.target.src}`));
  };
  document.body.appendChild(script);
});

In my case it was Next.js' 9.5.2 prefetching mechanism causing it on Firefox, just in case somebody has a similar case. (maybe here? https://github.com/getsentry/sentry-javascript/issues/2546#issuecomment-697771381) This is the issue: https://github.com/vercel/next.js/pull/16757 and can be solved by upgrading to 9.5.3 or Canary.

The error is much more verbose in the browser, though:

Uncaught (in promise) 
error
bubbles: false
...
...
as: "fetch"
assignedSlot: null
attributes: NamedNodeMap(3
0: href="/_next/data/wmQYPCwvbuBulJfEwTMRf/smartwatches/fitbit-ionic.json"
1: rel="prefetch"
2: as="fetch"
as: as="fetch"
href: href="/_next/data/wmQYPCwvbuBulJfEwTMRf/smartwatches/fitbit-ionic.json"
length: 3
rel: rel="prefetch"
...
...
​
isTrusted: true
originalTarget: <link href="/_next/data/wmQYPCwvbuBu…tches/fitbit-ionic.json" rel="prefetch" as="fetch">
returnValue: true
srcElement: <link href="/_next/data/wmQYPCwvbuBu…tches/fitbit-ionic.json" rel="prefetch" as="fetch">​
target: <link href="/_next/data/wmQYPCwvbuBu…tches/fitbit-ionic.json" rel="prefetch" as="fetch">
timeStmp: 25366
type: "error"
...

How can we get Sentry to capture this data?

@Turbo87 YES! This is exactly why we're only seeing it on pages using @googlemaps/js-api-loader. They're doing exactly what you're describing here

Thank you!!

Was this page helpful?
0 / 5 - 0 ratings