SIGN IN SIGN UP
facebook / react-native UNCLAIMED

A framework for building native applications using React

0 0 0 C++

surface uncaught promise rejections with ExceptionsManager.handleException instead of swallowing them (#51594)

Summary:
This PR fixes logging of rejections, which stopped working with the transition from using `LogBox` for warnings to directing users to use React Native Debugger, where warnings can be viewed in the `Console` tab.

Rejected promises before this PR used `LogBox.addLog` with the `level: warn` directly without `console.warn`, which notified users to open debugger to view a warning (after rejected promise) without actually printing any warnings to the console.

This PR uses `ExceptionsManager.handleException(error, false /* isFatal */);` for promise rejections that correctly raising an error to the console if needed.

### Rejected Promise in Chrome
Displaying the error as long as it's uncaught in the form:
`Uncaught (in promise) Error`
and if there's a message in that error:
`Uncaught (in promise) Error: ${message}`
once the error is handled, this error disappears:
{F1978806409}
This is done with `Runtime.exceptionThrown`, and  `Runtime.exceptionRevoked`:
{F1979815326}

## Changelog:
[General][Breaking] unhandled promises are now handled by ExceptionsManager.handleException, instead of being swallowed as Logbox Warnings.
----
This is a breaking change because we changed the wording for these errors and because some systems (like Sentry) might start monitoring a new set of errors when this code is adopted.

Pull Request resolved: https://github.com/facebook/react-native/pull/51594

Test Plan:
Use `Promise.reject` and observe that the rejection is now shown symbolicated in LogBox and also printed in React Native Debugger Console.

```
<Button
  title="Uncaught Promise Rejection"
  onPress={() => {
    const err = new Error('test error');
    err.cause = new Error('cause');
    const promise = Promise.resolve().then(() => {
      throw err;
      // also test with throwing a string / object:
      // throw 'aa';
      // throw {test: 'object'};
      // return Promise.reject();
    });

    setTimeout(() => {
      promise.catch(e => {
        console.log('promise error caught', e);
      });
    }, 4000);
  }}
/>
```

### Before
There's no indication whatsoever there's an uncaught promise.

### After
An error is logged:
Error-
{F1979749366}
Text-
{F1979749350}
Object-
{F1979749351}
Promise.reject() or undefined-
 {F1979749826}

Reviewed By: hoxyq

Differential Revision: D75442651

Pulled By: vzaidman

fbshipit-source-id: bf6c56e643f03997f5a604b85c543aad62648a29
K
Krystof Woldrich committed
c4082c9ce208a324c2d011823ca2ba432411aafc
Parent: 4ee2b60
Committed by Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> on 7/17/2025, 2:55:50 PM