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.

Copied
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.

  1. Check the version of promise that your version of react-native uses. You can do this by going into node_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
Copied
{
  "dependencies": {
    // ...
    "promise": "^8.0.3"
  }
}
  1. Add a package resolution with the same version as react-native's' to your package.json file, this will force this version to be used. You will then need to run a fresh yarn install or npm install to use the package resolution you just added.
package.json
Copied
{
  "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.

  1. 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 and dist and are set on the event by setting it in the call to init.
  • Checking that source maps are correctly uploaded with the exact same release and dist values as the event. They must match for source maps to upload correctly.
  • If you set a custom release and dist, 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 named index.bundle and index.bundle.map respectively.
  • Checking that you're not disabling the RewriteFrames default integration by overwriting it, filtering it out, or setting defaultIntegrations: 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:

Copied
# ...
../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
Copied
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:

Copied
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.

Copied
export SENTRY_DIST=$CI_BUILD_NUMBER

If you see an error like Unknown receiver 'SwiftDescriptor' or Use of undeclared identifier 'SentryLog' during the application build process, there's a conflict stemming from APPLICATION_EXTENSION_API_ONLY. By default, the Sentry Cocoapod is configured with APPLICATION_EXTENSION_API_ONLY=YES, but some post_install script likely changed it. To fix this error, add the following to the Podfile.```

ios/Podfile
Copied
post_install do |installer|
  react_native_post_install(
    installer,
    config[:reactNativePath],
    :mac_catalyst_enabled => false,
  )

  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      if target.name == 'Sentry'
        config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
      else
        # configuration for other targets
      end
    end
  end
end

If you have enabled Gradle's org.gradle.configureondemand feature, you'll need a clean build, or you'll need to disable this feature to upload the source map on every build.

To disable this feature, set org.gradle.configureondemand=false or remove it as its default value is disabled, do this in the gradle.properties file.

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.

Copied
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:

Copied
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:

Copied
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:

Copied
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:

Copied
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:

Copied
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
Copied
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
Copied
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:

Copied
# 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():

Copied
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:

Copied
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:

Copied
[Replace] [Anything] from [contexts.trace.data.route.params]
[Replace] [Anything] from [contexts.trace.data.previousRoute.params]

To remove the SDK from your project, run the following commands:

Copied
npx @sentry/wizard -i reactNative -p ios android --uninstall
yarn remove @sentry/react-native
cd ios && pod install

Once that's done, remove the ios/sentry.properties and android/sentry.properties files. Finally, remove all the code using @sentry/react-native from your project.

Help improve this content
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").