SDK & Framework Guides

React Native Crash Reporting

Capture both JavaScript and native crashes in React Native with the Sentry SDK, upload source maps and dSYMs, and get readable stack traces.

React Native apps crash in two distinct layers: the JavaScript thread where your components and business logic run, and the native thread where iOS or Android handles everything else. A single user action might trigger an error in either layer, and unless you're capturing from both, half your crashes disappear into silence. React native error tracking requires visibility into both to catch every failure and keep your app stable.

This guide sets up production-grade error tracking in a React Native app using the Sentry SDK pointed at LightTrace, so you capture JavaScript errors, native crashes, and the context that makes fixing them fast.

Install the React Native SDK

Start by adding the Sentry SDK for React Native. It includes hooks for both JavaScript and native crash reporting:

npm install @sentry/react-native
# or yarn
yarn add @sentry/react-native

# Link native modules (for React Native <0.60, use react-native link)
npx pod-install

The native linking step sets up crash reporters on both iOS and Android. This is different from web SDK setup — you're not just importing JavaScript; you're connecting to platform-specific crash handlers.

Initialize the SDK in your app entry point

Initialize Sentry once, as early as possible, before any of your app code runs. The SDK will install global handlers for both JavaScript exceptions and native crashes:

// index.js or index.native.js
import * as Sentry from "@sentry/react-native";

Sentry.init({
  dsn: "https://<key>@your-lighttrace-host/1",
  environment: process.env.NODE_ENV,
  release: "myapp@1.2.3",
  tracesSampleRate: 1.0,
  // Attach stack traces to all messages, not just errors
  attachStacktrace: true,
});

// Your app initialization code follows
import App from "./App";
import { AppRegistry } from "react-native";

AppRegistry.registerComponent("myapp", () => App);

That single init call hooks into React Native's JavaScript exception handler and registers native crash reporters on both iOS (for Objective-C/Swift exceptions) and Android (for Java exceptions and native crashes). From this point forward, unhandled errors on either layer report automatically.

Capture JavaScript errors with error boundaries

Your React Native components throw errors during render or in lifecycle methods. Unlike web React, the framework doesn't unmount your whole tree on an error — but you should still catch and report those exceptions:

import * as Sentry from "@sentry/react-native";

export class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, { contexts: { react: errorInfo } });
  }

  render() {
    if (this.state.hasError) {
      return <ErrorScreen />;
    }
    return this.props.children;
  }
}

Wrap your root navigator or tab bar in this boundary so component crashes are caught and logged before they crash the entire app. Every error arrives at LightTrace with the component stack, so you can pinpoint exactly which screen failed.

React Native doesn't have built-in Error Boundaries like web React — you must build them yourself. Wrapping your app's top-level navigator is often enough, but for large apps, you can add boundaries around each screen or tab.

Handle native crashes and crashes on the background thread

JavaScript errors are one thing. Native crashes — a segmentation fault in native code, an unhandled exception in a native module, or a crash on a background thread — won't hit your JavaScript error boundary. Sentry's native crash reporters catch these automatically once initialized, but understanding what they capture helps with debugging.

When a native crash occurs, Sentry's native layer captures:

  • The stack trace from the crashed thread (with file names and line numbers).
  • All thread states, so you can see what was happening on other threads.
  • The app state — foreground or background, memory pressure.
  • Custom breadcrumbs you've added from JavaScript.

The SDK batches and uploads these reports the next time the app launches. You'll see them in LightTrace alongside your JavaScript issues, with full stack traces so you can find the culprit in your code.

Upload source maps and dSYMs for readable traces

In production, your JavaScript is minified, and your native binaries are compiled. Without source maps and dSYM files, a stack trace points at index-a4f2.js:1:45821 or a memory address — useless. You need to upload:

Source maps for JavaScript: Generated by your bundler (Metro for React Native) and uploaded to LightTrace.

dSYM files for iOS: Debug symbol files generated by Xcode and uploaded after each release.

ProGuard mappings for Android: If you use ProGuard or R8 for minification, upload the mapping file.

Set up source map and dSYM upload in your CI/CD pipeline:

# After building for production
sentry-cli releases files upload-sourcemaps ./dist

# iOS: after building the app
sentry-cli releases files upload-dsyms ./ios/build/YourApp.app.dSYM

# Android: after building the release APK/AAB
sentry-cli releases files upload-proguard-mappings ./android/app/build/outputs/mapping/release/

Once uploaded, every stack frame maps back to your original source code. Learn more about source maps and dSYMs.

Tag releases and add context for faster debugging

A crash without context is just a number. Tag every event with the release so you can see which deploy introduced a regression:

Sentry.setTag("release_stage", "staging");
Sentry.setUser({ 
  id: user.id, 
  email: user.email 
});

Sentry.addBreadcrumb({
  category: "navigation",
  message: "Opened orders screen",
  level: "info",
});

Now every crash arrives with:

  • Release tag — pinpoint which build introduced the regression, and roll back if needed.
  • User info — see how many users hit it and who to contact for more details.
  • Breadcrumb trail — the exact sequence of events (screen transitions, API calls, user taps) leading up to the crash.

This context turns a bare stack trace into a reproducible scenario, cutting debugging time from hours to minutes.

Monitor crash-free rate and deploy health

Crashes that happen in production matter most. Track how stable each deploy is by monitoring the crash-free rate for each release — the percentage of sessions or users that completed without a crash. A small drop (95% → 92% crash-free) is a silent regression that hurts retention; tracking it tells you immediately when a deploy is problematic:

Sentry.captureMessage("User onboarding completed", "info");

Tag each build with a release so you can tie crashes back to the deploy that introduced them.

Key differences from web error tracking

React Native error tracking differs from web JavaScript error tracking in three ways:

  1. Native layer. You must capture crashes from native code, not just JavaScript. The SDK does this automatically, but it's why setup is more involved than the web SDK.

  2. No source maps during development. In development, stack traces are already readable because the app runs unbundled. But production builds are bundled and minified, so source maps and dSYMs are essential.

  3. Background threads. Native code often runs on background threads. The SDK captures crashes there too, so you see failures that never touch JavaScript.

For more framework-specific guides, see how to set up error tracking for Android, iOS, and Flutter. If you're adding error tracking to a new app from scratch, the universal setup guide covers the pattern across every language.

Test your setup

Before shipping to production, verify that crashes actually report:

// Add a test button that throws an error
<Button 
  title="Test Error" 
  onPress={() => {
    throw new Error("Test error from button");
  }}
/>

// Test a native crash (iOS)
Sentry.nativeCrash();

Deploy to a staging build, trigger the error, and check LightTrace to confirm it arrived with full context. Once you see the first real issue grouped and tagged with your release, you're ready for production.

Start tracking errors in minutes

Point the Sentry SDK at LightTrace and start capturing React Native crashes — both JavaScript and native — from day one.

That's the full setup: SDK initialized for both layers, error boundaries catching component crashes, source maps and dSYMs making traces readable, and context making them fast to fix. React Native apps crash, but with this foundation in place, you'll know about it before your users do.

Fix your next production error faster

Point any Sentry SDK at LightTrace — free up to 5,000 events/month.