Expo
Learn how to set up an Expo project with Sentry's React Native SDK, including the Sentry Expo config plugin, Expo Router tracing, Expo Updates context, and the EAS dashboard integration.
Use curl to download, read and follow https://skills.sentry.dev/instrument to set up the Sentry Expo SDK.Use this guide to get fully set up with Sentry's React Native SDK in an Expo project. The same @sentry/react-native SDK powers both bare React Native and Expo apps. This guide covers the Expo-specific setup (config plugin, Metro, EAS) and integrations.
If you don't already have an account and Sentry project established, head over to sentry.io, then return to this page.
- Expo SDK 50 or newer. The
@sentry/react-nativeSDK requires Expo SDK 50+.- On Expo SDK 49 or older, the legacy
sentry-expopackage was used. It's now deprecated — migrate to@sentry/react-nativeto keep receiving updates.
- On Expo SDK 49 or older, the legacy
- Sign up for an account.
Use the Sentry Wizard to patch your project automatically, as shown below. Alternatively, you can follow the Manual Install if you prefer. You only need to patch the project once. Then, you can add the patched files to your version control system.
npx @sentry/wizard@latest -i reactNative
npx @sentry/wizard@latest -i reactNative
If you don't use the Wizard, install the @sentry/react-native package:
npx expo install @sentry/react-native
npx expo install @sentry/react-native
npm install @sentry/react-native --save
yarn add @sentry/react-native
pnpm add @sentry/react-native
Import the @sentry/react-native package and call init with your DSN:
import { Stack } from "expo-router";
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: "___PUBLIC_DSN___",
// Adds more context data to events (IP address, cookies, user, etc.)
// For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/
sendDefaultPii: true,
// ___PRODUCT_OPTION_START___ performance
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
// We recommend adjusting this value in production.
// Learn more at
// https://docs.sentry.io/platforms/react-native/configuration/options/#traces-sample-rate
tracesSampleRate: 1.0,
// ___PRODUCT_OPTION_END___ performance
// ___PRODUCT_OPTION_START___ logs
// Enable logs to be sent to Sentry
// Learn more at https://docs.sentry.io/platforms/react-native/logs/
enableLogs: true,
// ___PRODUCT_OPTION_END___ logs
// ___PRODUCT_OPTION_START___ profiling
// profilesSampleRate is relative to tracesSampleRate.
// Here, we'll capture profiles for 100% of transactions.
profilesSampleRate: 1.0,
// ___PRODUCT_OPTION_END___ profiling
// ___PRODUCT_OPTION_START___ session-replay
// Record session replays for 100% of errors and 10% of sessions
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
integrations: [Sentry.mobileReplayIntegration()],
// ___PRODUCT_OPTION_END___ session-replay
});
function RootLayout() {
return <Stack />;
}
export default Sentry.wrap(RootLayout);
import { Stack } from "expo-router";
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: "___PUBLIC_DSN___",
// Adds more context data to events (IP address, cookies, user, etc.)
// For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/
sendDefaultPii: true,
// ___PRODUCT_OPTION_START___ performance
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
// We recommend adjusting this value in production.
// Learn more at
// https://docs.sentry.io/platforms/react-native/configuration/options/#traces-sample-rate
tracesSampleRate: 1.0,
// ___PRODUCT_OPTION_END___ performance
// ___PRODUCT_OPTION_START___ logs
// Enable logs to be sent to Sentry
// Learn more at https://docs.sentry.io/platforms/react-native/logs/
enableLogs: true,
// ___PRODUCT_OPTION_END___ logs
// ___PRODUCT_OPTION_START___ profiling
// profilesSampleRate is relative to tracesSampleRate.
// Here, we'll capture profiles for 100% of transactions.
profilesSampleRate: 1.0,
// ___PRODUCT_OPTION_END___ profiling
// ___PRODUCT_OPTION_START___ session-replay
// Record session replays for 100% of errors and 10% of sessions
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
integrations: [Sentry.mobileReplayIntegration()],
// ___PRODUCT_OPTION_END___ session-replay
});
function RootLayout() {
return <Stack />;
}
export default Sentry.wrap(RootLayout);
Wrap the root component of your application with Sentry.wrap:
export default Sentry.wrap(RootLayout);
export default Sentry.wrap(RootLayout);
To ensure bundles and source maps are automatically uploaded during the native application builds, add the Sentry plugin to your Expo app configuration. Add it to the plugins array in app.json, or wrap your config with withSentry in app.config.js/app.config.ts:
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"url": "https://sentry.io/",
"note": "Use SENTRY_AUTH_TOKEN env to authenticate with Sentry.",
"project": "___PROJECT_SLUG___",
"organization": "___ORG_SLUG___"
}
]
]
}
}
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"url": "https://sentry.io/",
"note": "Use SENTRY_AUTH_TOKEN env to authenticate with Sentry.",
"project": "___PROJECT_SLUG___",
"organization": "___ORG_SLUG___"
}
]
]
}
}
const { withSentry } = require("@sentry/react-native/expo");
const config = {
name: "Expo Example",
slug: "expo-example",
};
module.exports = withSentry(config, {
url: "https://sentry.io/",
// Use SENTRY_AUTH_TOKEN env to authenticate with Sentry.
project: "___PROJECT_SLUG___",
organization: "___ORG_SLUG___",
});
import { ExpoConfig } from "expo/config";
import { withSentry } from "@sentry/react-native/expo";
const config: ExpoConfig = {
name: "Expo Example",
slug: "expo-example",
};
export default withSentry(config, {
url: "https://sentry.io/",
// Use SENTRY_AUTH_TOKEN env to authenticate with Sentry.
project: "___PROJECT_SLUG___",
organization: "___ORG_SLUG___",
});
npx expo install adds the bare @sentry/react-native to the plugins array. Both @sentry/react-native and @sentry/react-native/expo are valid plugin paths. Expo resolves them the same way.
Add your auth token to a .env.local file in the root of your project:
.env.local# DO NOT COMMIT YOUR AUTH TOKEN
SENTRY_AUTH_TOKEN=___ORG_AUTH_TOKEN___
# DO NOT COMMIT YOUR AUTH TOKEN
SENTRY_AUTH_TOKEN=___ORG_AUTH_TOKEN___
Do not commit your auth token. Add .env.local to your .gitignore. For EAS builds, add SENTRY_AUTH_TOKEN as an EAS secret instead of using a .env.local file.
To ensure unique Debug IDs get assigned to the generated bundles and source maps, add Sentry Serializer to the Metro configuration:
// const { getDefaultConfig } = require("expo/metro-config");
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
// const config = getDefaultConfig(__dirname);
const config = getSentryExpoConfig(__dirname);
module.exports = config;
// const { getDefaultConfig } = require("expo/metro-config");
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
// const config = getDefaultConfig(__dirname);
const config = getSentryExpoConfig(__dirname);
module.exports = config;
The SDK needs access to certain information about the device and the application for its essential functionality. Some of the APIs required for this are considered privacy-relevant. Add the privacy manifest to your Xcode project to ensure your app is compliant with Apple's guidelines. Read the Apple Privacy Manifest guide for more info on how to add records required for the Sentry SDKs.
To verify that everything is working as expected, build the Release version of your application and send a test event to Sentry by adding:
<Button
title="Try!"
onPress={() => {
Sentry.captureException(new Error("First error"));
}}
/>;
<Button
title="Try!"
onPress={() => {
Sentry.captureException(new Error("First error"));
}}
/>;
- Expo Updates — Automatic OTA update context, searchable tags, and emergency launch alerts
- EAS Build Hooks — Capture build failures and lifecycle events from EAS Build
- Sentry Android Gradle Plugin — Advanced Android build configuration
- Expo Router tracing — Navigation transitions, performance spans, prefetch instrumentation, and per-route
ErrorBoundarycapture - Expo Image and Asset tracing — Automatic spans for
expo-imageandexpo-asset - Upload source maps for native builds and Expo Updates
- Don't commit your auth token. Store it in
.env.localasSENTRY_AUTH_TOKENfor local builds, and as an EAS secret for EAS builds. - Source maps for the
Releaseversion of your application are uploaded automatically during the native application build. - During development, the source code is resolved using the Metro Server and source maps aren't used. This currently doesn't work on web.
Once the SDK is set up, you can also connect Sentry to Expo Application Services (EAS) so crash reports and Session Replays for your deployments show up directly in your EAS dashboard, with direct links to Sentry stack traces and full debugging context.
If you change your organization slug, you'll need to update your configuration for this integration. Learn more in our troubleshooting guide.
Sentry owner, manager, or admin permissions are required to install this integration.
- Log in to your Expo dashboard and open Account Settings > Overview (
https://expo.dev/accounts/[your-account]/settings). - Locate the Connections section and click Connect next to Sentry.
- Log in to Sentry and accept the integration into your organization. You'll be redirected back to Account Settings > Overview.
After connecting your accounts, link your Expo project to your Sentry project:
- Open Projects > [Your Project] > Configuration > Project settings in the Expo dashboard.
- Click Link and select your Sentry project from the dropdown.
To see your Sentry issues and replays in the Expo dashboard, first make sure you've created an EAS Update channel and assigned builds to it to create an EAS deployment. Then:
- Open Projects > [Your Project] > Updates > Deployments > [Deployment] to view Sentry data from a release.
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").