Troubleshooting
Troubleshoot and resolve common issues with the React Native SDK.
Starting May 1, 2024, Apple requires all apps submitted to the App Store to provide a list of privacy-related APIs they use, including the reasons under which they use it. If you received an email from Apple with the message "ITMS-91053: Missing API declaration", your app doesn't fulfill the requirements. To solve this, follow our Apple Privacy Manifest guide.
iOS 15 introduced a feature called pre-warm that affected the calculations the Sentry SDK does. This issue was fixed in version 4.1.1 of the SDK. Please update to this version or a later one.
For more details, see the troubleshooting page for the iOS SDK.
Due to an issue with React Native's dependencies, unhandled promise rejections might not be correctly caught by Sentry. 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.
When there is an issue with source maps on your event, there will usually be an error dialog at the top of the Issue Details page in sentry.io:
There was 1 problem processing this event: Source code was not found
Common fixes to this issue include:
- Checking that both the
release
anddist
and are set on the event by setting it in the call toinit
. - Checking that source maps are correctly uploaded with the exact same
release
anddist
values as the event. They must match for source maps to upload correctly. - If you set a custom
release
anddist
, confirming that you manually uploaded the sourcemaps since our automatic source map upload script will not detect the custom values. - Make sure that the name of the bundle in the stack trace matches exactly with the name in the source map. For example, if your stack frames say
app:///index.bundle
, the artifacts must be namedindex.bundle
andindex.bundle.map
respectively. - Checking that you're not disabling the
RewriteFrames
default integration by overwriting it, filtering it out, or settingdefaultIntegrations: false
.
For more details, please read the guide on React Native source maps.
Although the build script should already handle this for you most of the time, you may need to perform some extra steps when using the source maps with the Hermes engine. You can follow the guide here..
Your app could have different bundles for each platform that it supports, such as iOS and Android. To associate the correct bundle and sourcemap to each platform, you will need a unique release/dist combination for each platform. An easy way to do this is to include the platform name in the dist
value.
If you're using an older version of the SDK (version 3.2.12
or lower) or sentry-cli
(version 1.71.0
or lower), try passing --force-foreground
to the Sentry CLI command in the build script:
# ...
../node_modules/@sentry/cli/bin/sentry-cli react-native xcode \
../node_modules/react-native/scripts/react-native-xcode.sh --force-foreground
If your release health statistics are being attributed to the wrong release, confirm that you pass the release
and dist
to the init
call.
If you are using Code Push, check that you are not using setRelease
and setDist
as they will break release health. You can read more on the CodePush guide.
When bundling for production, React Native will minify class and function names to reduce the bundle size. This means that you won't get the full original component names in your Touch Event breadcrumbs or Profiler spans.
A way to work around this is to set the displayName
on all the components you want to track with touch events or to pass the name
prop to the Profiler components. However, you can also configure Metro bundler to not minify function names by setting these options in metro.config.js
:
metro.config.js
module.exports = {
transformer: {
minifierConfig: {
keep_classnames: true, // Preserve class names
keep_fnames: true, // Preserve function names
mangle: {
keep_classnames: true, // Preserve class names
keep_fnames: true, // Preserve function names
},
},
},
};
This setting applies to all class and function names — not just React components — and could increase your JS bundle size.
If the context - such as breadcrumbs, user, etc. - is missing on Android NDK events, you need to enable the Scope Synchronization feature.
Xcode has trouble locating the default node binary if you're using nvm or Volta. To troubleshoot this, add node
binary path to the Bundle React Native code and images build phase like this:
export NODE_BINARY=path/to/your/node
# ... rest of the script
Or execute this ln -s $(which node) /usr/local/bin/node
in your terminal.
If you're using React Navigation 5
and you're not receiving transactions anymore, it might be because of this bug. Upgrading to React Navigation 6
should solve the issue, but if not, file an issue in our repo.
If you experience mismatched line numbers on sentry.io when using RAM Bundles, this is due to a bug on the Metro tooling.
The Xcode integration reads dist
from CFBundleVersion
but Xcode Cloud builds use CI_BUILD_NUMBER
variable. Add the following code to Bundle React Native code and images
build phase to enable correct source maps uploads.
export SENTRY_DIST=$CI_BUILD_NUMBER
To install an older version of the @sentry/react-native
, you'll need to specify it in the install command. Similarly, you'll need to use a compatible @sentry/wizard
, as shown in the script below.
yarn add @sentry/react-native@4
npx @sentry/wizard@1 -i reactNative -p ios android
npx pod-install
Before building the app, check that the android/app/build.gradle
was patched with the following Gradle integration:
apply from: "../../node_modules/@sentry/react-native/sentry.gradle"
While this should work on Android, it will still fail in the Bundle React Native code and images
build step phase on iOS. To fix this, revert the patched shellScript
in the ios/$projectName.xcodeproj/project.pbxproj
file, (where $projectName
is likely your project's name). Then search for the build step phase Bundle React Native code and images
and patch the shellScript
.
Old:
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
New:
shellScript = "set -e\nexport SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\nSENTRY_CLI_PATH=\"../node_modules/@sentry/cli/bin/sentry-cli\"\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$SENTRY_CLI_PATH react-native xcode $REACT_NATIVE_XCODE\\\"\"";
If your build is failing because of outdated fields in the react-native.config.js
, update the config file, located in node_modules/@sentry/react-native/react-native.config.js
. This is required for React Native, v0.69. For now, newer versions only show a warning.
Old:
module.exports = {
dependency: {
platforms: {
ios: {
sharedLibraries: ['libz'],
},
android: {
packageInstance: 'new RNSentryPackage()',
},
},
hooks: {
postlink:
'node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android',
postunlink:
'node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android --uninstall',
},
},
};
New:
module.exports = {
dependency: {
platforms: {
ios: {},
android: {
packageInstance: 'new RNSentryPackage()',
},
},
},
};
React Native 0.60.3 tooling was unexpectedly moving source maps files, which caused the Sentry Gradle plugin to fail. This was fixed in version 0.60.4. For more detailed information, follow the issue.
If you're using SDK v5.10.0 or older, use the following build phases in Xcode. If you are using SDK v5.11.0 or newer, read the current Manual Setup.
Bundle React Native code and images
export SENTRY_PROPERTIES=sentry.properties
export EXTRA_PACKAGER_ARGS="--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map"
set -e
# RN 0.69+
WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
REACT_NATIVE_XCODE="../node_modules/react-native/scripts/react-native-xcode.sh"
SENTRY_CLI="../node_modules/@sentry/cli/bin/sentry-cli"
/bin/sh -c "$WITH_ENVIRONMENT \"$SENTRY_CLI react-native xcode $REACT_NATIVE_XCODE\""
# RN 0.46 – 0.68
# ../node_modules/@sentry/cli/bin/sentry-cli react-native xcode \
# ../node_modules/react-native/scripts/react-native-xcode.sh
# All versions
/bin/sh ../node_modules/@sentry/react-native/scripts/collect-modules.sh
And Build Phase for native debug symbols upload.
Upload Debug Symbols to Sentry
export SENTRY_PROPERTIES=sentry.properties
[[ $SENTRY_INCLUDE_NATIVE_SOURCES == "true" ]] && INCLUDE_SOURCES_FLAG="--include-sources" || INCLUDE_SOURCES_FLAG=""
SENTRY_CLI="../node_modules/@sentry/cli/bin/sentry-cli"
$SENTRY_CLI debug-files upload "$INCLUDE_SOURCES_FLAG" "$DWARF_DSYM_FOLDER_PATH"
If you're using the new architecture on React Native, you might be missing the Java stack trace. Follow the issue for more information.
If your build fails due to Sentry CLI error, because you don't have internet connection, or because sentry.io is down, you can allow failure of the sentry-cli
step by adding an environmental variable SENTRY_ALLOW_FAILURE
equal to true
. The CLI will still run, but won't cause the build to fail:
# iOS
SENTRY_ALLOW_FAILURE=true npx react-native run-ios
# Android
SENTRY_ALLOW_FAILURE=true npx react-native run-android
Note that if the source maps upload fails, you'll have to do it manually later when the connection is restored.
When you remove the environmental variable in front of your build command, your build will work as before.
If you're using expo-dev-client, you might notice that transactions never finish in your dev builds. This is due to logs that the dev client is continuously sending to the development server. To fix this, you can stop creating spans for the HTTP requests to the log endpoint in your dev builds by adding the following to your Sentry.init()
:
import * as Sentry from "sentry-expo";
import * as Network from "expo-network";
const devServerPort = 8081;
let devServerIpAddress: string | null = null;
Network.getIpAddressAsync().then((ip) => {
devServerIpAddress = ip;
});
Sentry.init({
tracesSampleRate: 1.0,
integrations: [
new Sentry.Native.ReactNativeTracing({
shouldCreateSpanForRequest: (url) => {
return (
!__DEV__ ||
!url.startsWith(`http://${devServerIpAddress}:${devServerPort}/logs`)
);
},
}),
],
});
If you use automatic routing instrumentation for React Navigation, sensitive data you put in routing parameters can get sent to Sentry. You can prevent this by either updating the SDK to 5.15.2 or higher, or dropping the data manually with beforeSendTransaction
:
Sentry.init({
dsn: '...',
beforeSendTransaction: event => {
// delete params as they may contain PII
delete event.contexts?.trace?.data?.route?.params;
delete event.contexts?.trace?.data?.previousRoute?.params;
return event;
},
});
You can also use Advanced Data Scrubbing to filter out sensitive data before it is stored on the server side:
[Replace] [Anything] from [contexts.trace.data.route.params]
[Replace] [Anything] from [contexts.trace.data.previousRoute.params]
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").