
Expo Crash Reporting: Complete Setup Guide
Expo managed workflow apps trade flexibility for simplicity — you don't touch native code, but you also can't use arbitrary native modules. Crash reporting in a managed workflow app has a few specific constraints you need to know about before you start.
This guide covers everything: installing the SDK in a managed project, configuring EAS Build for source maps, tracking navigation with Expo Router, and verifying your setup works in production.
Managed vs Bare Workflow: What's Different
In a bare workflow app, you run npx pod-install and link native modules directly. In a managed workflow app, Expo manages native code for you — you can only use modules that Expo's managed infrastructure supports.
BugsPulse's React Native SDK works in managed workflow because it uses Expo-compatible native modules. Install with npx expo install (not npm install) to ensure the correct compatible version is resolved:
npx expo install @bugspulse/react-nativeNo pod-install, no android/ edits needed.
Initialization
Initialize BugsPulse in your root _layout.tsx (Expo Router) or App.tsx (Expo classic):
// app/_layout.tsx (Expo Router)
import BugsPulse from '@bugspulse/react-native';
import { useEffect } from 'react';
import { Stack } from 'expo-router';
BugsPulse.init({
apiKey: process.env.EXPO_PUBLIC_BUGSPULSE_KEY!,
environment: process.env.EXPO_PUBLIC_ENV ?? 'production',
sessionReplay: true,
captureNetworkRequests: true,
});
export default function RootLayout() {
return <Stack />;
}Store your API key in a .env.local file — Expo's config system picks up any EXPO_PUBLIC_ prefixed variable automatically:
# .env.local
EXPO_PUBLIC_BUGSPULSE_KEY=bp_your_project_key
EXPO_PUBLIC_ENV=productionExpo Router Navigation Tracking
Expo Router is file-based routing built on React Navigation. To track screen views as breadcrumbs:
// app/_layout.tsx
import { useNavigationContainerRef } from 'expo-router';
import BugsPulse from '@bugspulse/react-native';
import { useEffect, useRef } from 'react';
import { Stack } from 'expo-router';
export default function RootLayout() {
const routeNameRef = useRef<string | undefined>();
return (
<Stack
screenOptions={{ headerShown: false }}
// Track navigation on each route change
>
{/* Use Expo Router's built-in navigation events */}
</Stack>
);
}For Expo Router v3+, use the useSegments hook to capture the current route:
import { useSegments, usePathname } from 'expo-router';
import { useEffect } from 'react';
import BugsPulse from '@bugspulse/react-native';
function NavigationTracker() {
const pathname = usePathname();
useEffect(() => {
BugsPulse.setCurrentScreen(pathname);
BugsPulse.addBreadcrumb({
message: `Navigated to ${pathname}`,
category: 'navigation',
});
}, [pathname]);
return null;
}
// Add <NavigationTracker /> inside your RootLayoutEAS Build + Source Maps
Without source maps, production crash stack traces are unreadable. EAS Build can generate them automatically.
eas.json configuration
{
## Related reading
- [React Native Crash Reporting: The Complete Setup Guide (2026)](/blog/react-native-crash-reporting-setup-guide)
- [React Native Error Tracking in Production: A Complete Guide](/blog/react-native-error-tracking)
- [The Complete Guide to React Native Crash Debugging](/blog/react-native-crash-debugging-guide)
**Try BugsPulse free** — event-based session replay, AI-powered crash analysis, and native crash capture for React Native and Flutter. 500 sessions/month, no credit card required. [Get started at bugspulse.com](https://bugspulse.com)