Setting Up Network Error Monitoring in Mobile Applications
Production app without network error monitoring—that's when you learn about issues from App Store reviews. Typical scenario: backend returned 502 at 3 AM, 8% of users got blank screen, some deleted the app. In Sentry, this becomes an event with full context: device, OS version, endpoint, response status, error body.
What to Monitor
Network errors fall into categories with different severity:
| Error Type | Example | Priority |
|---|---|---|
| Connectivity | Network request failed, timeout |
High—user can't work |
| 4xx Client | 401, 403, 404, 422 | Medium—often expected |
| 5xx Server | 500, 502, 503, 504 | High—backend problem |
| Parse error | JSON decode failure | High—breaking API change |
| SSL/TLS | Certificate pinning failure | Critical—possible attack |
Sentry for React Native: Intercept Network Requests
@sentry/react-native automatically intercepts fetch and XMLHttpRequest via global object patching. By default, includes Performance traces for HTTP requests but doesn't log errors automatically:
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: 'https://[email protected]/yyy',
tracesSampleRate: 0.1, // 10% of requests traced for Performance
integrations: [
new Sentry.ReactNativeTracing({
traceFetch: true,
traceXHR: true,
// Don't include sensitive endpoints in traces
tracingOrigins: ['api.yourapp.com', 'cdn.yourapp.com'],
}),
],
});
For explicit network error logging—wrapper over fetch:
export async function monitoredFetch(
url: string,
options?: RequestInit
): Promise<Response> {
const startTime = Date.now();
try {
const response = await fetch(url, options);
const duration = Date.now() - startTime;
if (!response.ok) {
Sentry.captureMessage(`HTTP ${response.status}: ${url}`, {
level: response.status >= 500 ? 'error' : 'warning',
extra: {
status: response.status,
duration,
method: options?.method ?? 'GET',
endpoint: new URL(url).pathname,
},
fingerprint: [`http-${response.status}`, new URL(url).pathname],
});
}
return response;
} catch (error) {
Sentry.captureException(error, {
extra: { url, duration: Date.now() - startTime },
tags: { error_type: 'network_connectivity' },
});
throw error;
}
}
fingerprint is critical. Without it, Sentry creates separate issue for each error URL. With fingerprint ['http-500', '/api/orders'], all 500 errors on /api/orders group into one issue.
Breadcrumbs: Context Before Error
Breadcrumbs show what happened before network error: which screens user opened, which actions performed:
// Add breadcrumb on navigation
navigation.addListener('state', (e) => {
Sentry.addBreadcrumb({
category: 'navigation',
message: `Navigate to ${e.data.state.routes[e.data.state.index].name}`,
level: 'info',
});
});
By default, stores last 100 breadcrumbs. For long sessions—sufficient.
Detect Connection Loss
Offline errors should separate from server errors. User in subway—not backend problem:
import NetInfo from '@react-native-community/netinfo';
let isConnected = true;
NetInfo.addEventListener(state => { isConnected = state.isConnected ?? true; });
// In monitoredFetch, on catch:
if (!isConnected) {
// Don't send to Sentry — expected offline
throw new OfflineError('No network connection');
}
// Otherwise — real error, log it
Sentry.captureException(error, { tags: { connectivity: 'online' } });
Alerting
Sentry Alerts on condition: count(event) > 50 per 5min for http-500 → Slack/PagerDuty. Error rate above baseline → alert. For production, should work 24/7.
Estimate
Sentry setup with network monitoring, fingerprinting, offline detection, and alerts: 1–2 weeks.







