Unhandled promise rejections

Author: skellockCreated Dec 29, 2017Updated Oct 20, 2025
Labelsrequest :+1:

Problem

Async error reporting is an awful dev experience.

image

We don't get a red box, we get a yellow box with a string representation of the stack trace.

So let's pipe unhandled promise rejections into Reactotron as if they were normal synchronous errors.

image

Overview

Looks like there's a few ways to do this. Each more ghetto than the next. I'm ok with this.

Since 0.44 of React Native, they started tracking unhandled exceptions as a yellow box. In their promise module, they've got some hooks to inject in your own tracking. And this is what React Native does.

Option 1

This is how React Native gets their yellow box on the screen. In the onUnhandled, they do some pretty printing and display the error. Which is pretty much never what I personally want to see.

To me, an unhandled promise rejection is an error. Full stop.

In this implementation, we just report the error (which runs the source map lookup gauntlet).

javascript
if (__DEV__) {
  require("promise/setimmediate/rejection-tracking").enable({
    allRejections: true,
    onUnhandled: (id, error = {}) => {
      console.tron.reportError(error)
    },
    onHandled: () => {},
  })
}

Option 2

The problem with the first option is that it replaces the yellow box behaviour entirely. I'm not sure I'm cool with that. We don't want to diverge too far from what RN devs expect.

This implementation will do both. It'll log the error with Reactotron and still put up the yellow box. We just swizzle good ol' _87. ‍♂️

A nice side-effect of this is that we don't have to wait for the hardcoded 2 second delay on most errors that flow thru unhandled promises.

Also, I'm not sure if error trackers like mobile center and crashlytics hook these same things, but if they do, this is the safer of the two options.

javascript
if (__DEV__) {
  const old87 = Promise._87
  const new87 = (promise, err) => {
    console.tron.reportError(err)
    old87(promise, err)
  }
  Promise._87 = new87
}

Option 3

There might be other ways to do this. I'm open to suggestions.

For example, we might be able to swizzle console.warn and parse it like that? Seems like it might be a bit fragile because we'd have to do some string parsing to filter unhandled rejections.

Where To Put This

Probably right inside the track error handling function in reactotron-react-native I'd reckon.

We could likely remove the if (__DEV__) parts since that should already be protected up at the app. Reactotron shouldn't be installed in production mode unless folks really want to. In which case, they know what they're doing.