from SDK installation to symbolicated stack traces
A crash that never shows up in a dashboard never gets fixed. Sentry crash reporting captures JavaScript errors and native iOS and Android crashes in React Native apps alike, symbolicates the stack traces, and makes visible what users actually experience, before a bad app store review becomes the first signal.
Table of Contents
- 1. What crash reporting in React Native really solves
- 2. SDK setup: installing @sentry/react-native
- 3. Source maps and readable JS stack traces
- 4. Native crashes: dSYM and ProGuard mapping
- 5. Breadcrumbs and enriching context
- 6. Release health and sessions
- 7. Performance tracing beyond crash reporting
- 8. Integrating sentry-cli into CI/CD pipelines
- 9. Sentry compared to Bugsnag and Crashlytics
- 10. Summary
- 11. FAQ
1. What crash reporting in React Native really solves
A React Native app lives in two runtimes at once: the JavaScript engine (Hermes or JSC) and the native iOS or Android layers. An error can originate in either, but without Sentry crash reporting a development team sees none of it. The user sees a red screen, closes the app, or uninstalls it. The error message, device type, operating system version, and exact code path stay unknown unless someone manually reports the incident to support.
This is exactly where crash reporting with Sentry comes in: an installed SDK automatically captures unhandled JavaScript exceptions, promise rejections, and native signal crashes, enriches them with context, and sends them to a central dashboard. The team learns within minutes, not weeks, that a new release is crashing on specific Android devices, and can pinpoint the exact line in the source code instead of guessing at symptoms.
The difference between an app with and without Sentry crash reporting shows up most clearly right after a release: without monitoring, problems surface through declining store ratings and support tickets, often days later. With Sentry, a spike in error rate appears in the dashboard within minutes, tied to the exact release version, affected device model, and a stack trace that leads straight to the faulty line of code.
2. SDK setup: installing @sentry/react-native
Installing @sentry/react-native starts with the Sentry wizard, which automatically adjusts the native configuration for iOS and Android, registers the Metro bundler hook for source maps, and writes the base configuration into the app's entry file. The wizard replaces manual edits to AppDelegate.mm and MainApplication.kt that were still needed in older Sentry versions.
Central to the setup is calling Sentry.init() as early as possible in the app lifecycle, before the root component renders. The DSN (data source name) identifies the Sentry project, tracesSampleRate controls the performance sampling rate, and enableNative activates the connection to the native crash handlers of sentry-cocoa and sentry-android. Without this native coupling, Sentry crash reporting would only see JavaScript errors and completely miss crashes originating in native modules.
// App.tsx — initialize Sentry as early as possible in the app lifecycle
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
environment: __DEV__ ? 'development' : 'production',
tracesSampleRate: 0.2,
enableNative: true,
enableAutoSessionTracking: true,
release: 'my-app@2.4.0+42',
beforeSend(event) {
// Strip personally identifiable data before it leaves the device
if (event.user) {
delete event.user.email;
}
return event;
},
});
export default Sentry.wrap(function App() {
return <RootNavigator />;
});
3. Source maps and readable JS stack traces
A JavaScript bundle in a production build is minified. Without source maps, Sentry crash reporting only delivers cryptic line numbers in a compressed file, with no mapping back to the actual source code. The Sentry Metro plugin automatically generates source maps during bundling and uploads them via sentry-cli, tied to the exact release version and build.
The critical part is that the release identifier used on the client must exactly match the one used during source map upload. If it diverges, Sentry finds no matching mapping and keeps displaying minified code. A CI step that keeps release creation, source map upload, and deployment reliably in sync prevents this common failure mode entirely.
#!/usr/bin/env bash
# Upload source maps for a production release before app store submission
set -euo pipefail
RELEASE="my-app@2.4.0+42"
sentry-cli releases new "$RELEASE"
sentry-cli releases files "$RELEASE" upload-sourcemaps \
./dist \
--dist 42 \
--rewrite
sentry-cli releases finalize "$RELEASE"
echo "Source maps uploaded and release finalized: $RELEASE"
4. Native crashes: dSYM and ProGuard mapping
Native crashes often originate in third-party libraries, in native modules with memory errors, or in bridging code between JavaScript and the native layer. For Sentry crash reporting to deliver readable stack traces here instead of just memory addresses, the dSYM file for every build must be uploaded on the iOS side. It contains the debug symbols that map an address in compiled binary code back to a function and line.
On the Android side, the ProGuard or R8 mapping file plays the same role for obfuscated code. Without this mapping, a crash report shows only renamed classes and method names such as a.b.c, which makes debugging practically impossible. The Sentry Gradle plugin automatically uploads the mapping file on every release build, provided it is correctly wired into build.gradle.
// ios/AppDelegate.mm — Sentry native SDK integration point for symbolicated crashes
// Xcode Build Phase "Upload Debug Symbols to Sentry" runs sentry-cli after archiving:
// sentry-cli debug-files upload --include-sources ./MyApp.xcarchive.dSYM.zip
//
// Ensure Build Settings > Debug Information Format is "DWARF with dSYM File"
// for both Debug and Release configurations, otherwise no dSYM is produced.
5. Breadcrumbs and enriching context
A stack trace alone rarely answers how a user ended up in the failing state. Breadcrumbs log the last actions before a crash: navigation events, API calls, button taps, and console output. Sentry crash reporting collects many of these breadcrumbs automatically, for example through the React Navigation integration, which logs every screen change.
On top of that, custom breadcrumbs and tags can be set, such as the pseudonymized user ID, the active feature flag set, or the cart state in a shopping app. This enrichment turns an isolated stack trace into a traceable story: which user, which state, which action immediately preceded the crash.
// Enrich crash reports with custom breadcrumbs and user context
import * as Sentry from '@sentry/react-native';
function addToCart(product: Product) {
Sentry.addBreadcrumb({
category: 'cart',
message: `Added product ${product.id} to cart`,
level: 'info',
});
cartStore.add(product);
}
Sentry.setUser({ id: hashUserId(currentUser.id) });
Sentry.setTag('feature_flag.checkout_v2', 'enabled');
6. Release health and sessions
Beyond individual crashes, Sentry crash reporting also delivers aggregated metrics: the crash-free session rate shows what percentage of app sessions ended without a crash, broken down by release version. A drop in this rate after a rollout is a reliable early warning signal, often before support tickets arrive.
Sessions are tracked automatically once enableAutoSessionTracking is enabled. For staged rollouts, for example through staged rollouts in the Play Store, the crash-free rate can be compared per rollout stage, enabling a data-driven decision on whether to halt or continue the rollout instead of relying on gut feeling.
7. Performance tracing beyond crash reporting
Sentry crash reporting and performance monitoring share the same infrastructure. With tracesSampleRate enabled, tracing measures app start times, navigation transitions, and network request durations without an additional SDK. A slow screen transition is often only revealed through these traces, whereas it would go unnoticed in classic crash reporting alone.
Especially valuable is linking traces to error events: a timeout on an API call that shortly afterward leads to a crash appears in the same dashboard as a connected sequence of events. This dramatically shortens root-cause analysis, because performance data and error data no longer need to be merged across separate tools.
8. Integrating sentry-cli into CI/CD pipelines
Manual source map and dSYM uploads are error-prone because they get forgotten easily. The robust solution wires sentry-cli directly into the release pipeline: after every successful build, a new Sentry release is created automatically, source maps and debug symbols are uploaded, and the release is marked as deployed.
This automation ensures that Sentry crash reporting delivers full symbolication from the first minute after rollout, instead of leaving a gap between app store approval and a manual upload. An additional CI step can even verify that a matching source map actually exists for every uploaded bundle, failing the build if it does not.
{
"sentryCliConfig": {
"org": "my-organization",
"project": "my-app-react-native",
"urlPrefix": "~/",
"rewrite": true,
"ignore": ["node_modules", "android", "ios"]
}
}
// android/app/build.gradle — Sentry Gradle plugin uploads ProGuard/R8 mapping automatically
// apply plugin: "io.sentry.android.gradle"
//
// sentry {
// autoUploadProguardMapping = true
// includeProguardMapping = true
// }
//
// This runs during `./gradlew assembleRelease` and requires SENTRY_AUTH_TOKEN
// to be present as an environment variable in the CI job.
9. Sentry compared to Bugsnag and Crashlytics
Sentry is not the only option for crash reporting in React Native, but the combination of an open ecosystem, combined error and performance monitoring, and a mature React Native integration makes it an obvious choice for teams that want more than pure crash reporting.
| Criterion | Sentry | Bugsnag | Firebase Crashlytics |
|---|---|---|---|
| Integrated performance tracing | Yes, same platform | Separate add-on product | Separate Firebase Performance SDK |
| Self-hosting possible | Yes, open source | No, SaaS only | No, Google Cloud only |
| Source map handling | Automated via Metro plugin | Manual via CLI | No native JS source map concept |
| Pricing model | Based on event volume | Based on user count | Free on the basic tier |
| Breadcrumb enrichment | Very flexible, many integrations | Solid, fewer integrations | Limited, Logcat-focused |
Firebase Crashlytics scores with a free entry point and deep Google Play integration, but falls behind Sentry crash reporting on source map handling and flexible context enrichment. Bugsnag is functionally close to Sentry, but requires a separate product for performance data. For teams that want crashes, performance, and releases in one tool, Sentry usually remains the more pragmatic choice.
Mironsoft
React Native monitoring, crash reporting and release automation
Catch crashes before your users report them?
We set up Sentry crash reporting in your React Native app end to end, including source maps, native symbolication, and CI integration, so every crash is traceable immediately.
Sentry setup
SDK integration, source maps and native symbolication for iOS and Android
CI/CD integration
Automated releases, sentry-cli uploads, and mapping verification
Monitoring consulting
Release health, alerting rules, and dashboard setup for your team
10. Summary
Sentry crash reporting turns invisible crashes into traceable, prioritizable error reports. Installing the SDK with Sentry.init() captures JavaScript errors, and the native coupling via sentry-cocoa and sentry-android extends coverage to native crashes. Source maps and dSYM uploads ensure stack traces stay readable instead of showing minified code or raw memory addresses.
Breadcrumbs and context tags turn an isolated error into a traceable user story, release health delivers aggregated metrics for rollout decisions, and integrating sentry-cli into the CI/CD pipeline ensures symbolication works from the first second after rollout. Combining these building blocks consistently cuts the time between crash and fix from days down to minutes.
React Native Crash Reporting with Sentry — Key Takeaways
SDK setup
Sentry.init() as early as possible, enableNative: true couples JS and native crash handlers.
Symbolication
Source maps for JS, dSYM for iOS, ProGuard/R8 mapping for Android, without these three stack traces stay unreadable.
Context
Breadcrumbs, tags, and release health turn a stack trace into a traceable story.
Automation
sentry-cli in the CI/CD pipeline prevents forgotten uploads and symbolication gaps.