Unhandled Promise Rejections
Learn about Sentry's Unhandled Promise Rejections handling in React Native.
Sentry automatically tracks unhandled promise rejections in React Native applications. Since version 6.15.0
the SDK uses engine-specific implementations to ensure reliable tracking across different JavaScript engines including Hermes, JavaScriptCore (JSC), and React Native Web environments.
Promise rejection tracking is enabled by default when you initialize Sentry. You can control promise rejection tracking through the reactNativeErrorHandlersIntegration
:
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [
Sentry.reactNativeErrorHandlersIntegration({
onunhandledrejection: false, // Disables promise rejection tracking
}),
],
});
When using Hermes, Sentry uses the engine's native promise rejection tracking capabilities.
Enabling Hermes rejection tracking will overwrite existing hooks due to limitations of the engine. Only one promise rejection tracker can be active at a time.
For JSC environments, Sentry uses Promise polyfill with rejection tracking capabilities. This approach also overwrites existing hooks.
The Promise polyfill is used to ensure compatibility and provide rejection tracking functionality that may not be available natively in older JSC versions.
For React Native Web, Sentry leverages the browser's native promise rejection tracking capabilities, providing seamless integration with web debugging tools.
When using multiple tools for promise rejection tracking, be aware that:
- Hermes: Only one rejection tracker can be active. Sentry will take precedence.
- JSC: Sentry's Promise polyfill will override existing handlers.
- React Native Web: Can coexist better with other browser-based debugging tools.
import * as Sentry from "@sentry/react-native";
// For development, you might want to disable Sentry's tracking
// to allow other debugging tools to handle promise rejections
if (__DEV__) {
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [
Sentry.reactNativeErrorHandlersIntegration({
onunhandledrejection: false, // Let other tools handle in development
}),
],
});
} else {
// In production, use Sentry's tracking
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
// Default configuration with promise tracking enabled
});
}
Due to an issue with React Native's dependencies, unhandled promise rejections might not be correctly caught by Sentry when using the JavaScriptCore (JSC) engine or a React Native SDK version before 6.15.0
.
If the promise rejection handler was not correctly attached, our SDK might issue a warning:
WARN: Unhandled promise rejections might not be caught by Sentry. Read about how to fix this on our troubleshooting docs.
Otherwise, we will let you know that the handler is attached:
[Sentry] Unhandled promise rejections will be caught by Sentry.
By default we will patch the global Promise
instance to ensure it matches exactly with the version that React Native uses.
If you use a polyfilling library that patches the global Promise
instance, you'll need to make sure you run the polyfill after Sentry.init
is called.
import allSettled from "promise.allsettled";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});
// Any Promise polyfilling must occur AFTER Sentry.init
// This step globally patches Promise.
allSettled.shim();
// Separate core-js example
import "core-js/stable/promise/all-settled";
Your linter might throw some errors here, but this step is necessary.
You can disable the global promise patching by passing patchGlobalPromise: false
in either Sentry.init
or the ReactNativeErrorHandlers
integration. Note that if you disable our auto patching, to ensure that unhandled rejections are still caught, you will need to manually force a package resolution.
You don't need to perform the steps below if you don't disable auto patching. You'll need to ensure that the version of promise
that you use matches exactly with the version that React Native uses.
- Check the version of
promise
that your version ofreact-native
uses. You can do this by going intonode_modules/react-native/package.json
and checking the version there, for example we find that it uses^8.0.3
:
node_modules/react-native/package.json
{
"dependencies": {
// ...
"promise": "^8.0.3"
}
}
- Add a package resolution with the same version as
react-native
's' to yourpackage.json
file, this will force this version to be used. You will then need to run a freshyarn install
ornpm install
to use the package resolution you just added.
package.json
{
"resolutions": {
"promise": "^8.0.3"
}
}
Package resolutions are currently only supporred by yarn
. If you use npm
, you can use a third-party package called npm-force-resolutions to achieve this.
- If the fix is successful, our SDK will no longer display the above warning and will indicate that promise rejections will be caught.
If you're upgrading from an older version of Sentry React Native:
- Remove any manual Promise polyfill resolutions from your
package.json
- Remove any custom promise rejection handling code
- Update to the latest version of
@sentry/react-native
- Test that promise rejections are being captured correctly
The new engine-specific approach should resolve previous compatibility issues automatically.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").