xref: /expo/docs/pages/routing/error-handling.mdx (revision a01fde37)
1---
2title: Error handling
3description: Learn how to handle unmatched routes and errors in your app when using Expo Router.
4---
5
6import ImageSpotlight from '~/components/plugins/ImageSpotlight';
7import { APIBox } from '~/components/plugins/APIBox';
8import { BoxLink } from '~/ui/components/BoxLink';
9import { BookOpen02Icon } from '@expo/styleguide-icons';
10
11This guide specifies how to handle unmatched routes and errors in your app when using Expo Router.
12
13## Unmatched routes
14
15<ImageSpotlight
16  alt="An example of unmatched routes displayed on all platforms."
17  src="/static/images/expo-router/unmatched.png"
18  style={{ maxWidth: 720 }}
19/>
20
21Native apps don't have a server so there are technically no 404s. However, if you're implementing a router universally, then it makes sense to handle missing routes. This is done automatically for each app, but you can also customize it.
22
23```js app/[...unmatched].js
24import { Unmatched } from 'expo-router';
25export default Unmatched;
26```
27
28This will render the default `Unmatched`. You can export any component you want to render instead. We recommend having a link to `/` so users can navigate back to the home screen.
29
30## Error handling
31
32Expo Router enables fine-tuned error handling to enable a more opinionated data-loading strategy in the future.
33
34<ImageSpotlight
35  alt="Using ErrorBoundary in Expo Router to catch errors in a route component."
36  src="/static/images/expo-router/error-boundaries.png"
37  style={{ maxWidth: 720 }}
38/>
39
40You can export a nested `ErrorBoundary` component from any route to intercept and format component-level errors using [React Error Boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary):
41
42{/* prettier-ignore */}
43```tsx app/home.tsx
44import { View, Text } from 'react-native';
45/* @info */
46export function ErrorBoundary(props: ErrorBoundaryProps) {
47/* @end */
48  return (
49    <View style={{ flex: 1, backgroundColor: "red" }}>
50      <Text>{props.error.message}</Text>
51      <Text onPress={props.retry}>Try Again?</Text>
52    </View>
53  );
54}
55export default function Page() { ... }
56```
57
58When you export an `ErrorBoundary` the route will be wrapped with a React Error Boundary effectively:
59
60```js Virtual
61function Route({ ErrorBoundary, Component }) {
62  return (
63    <Try catch={ErrorBoundary}>
64      <Component />
65    </Try>
66  );
67}
68```
69
70When `ErrorBoundary` is not present, the error will be thrown to the nearest parent's `ErrorBoundary`.
71
72### API
73
74<APIBox header="ErrorBoundaryProps">
75
76Each `ErrorBoundary` is passed the following props:
77
78- **error:** `Error` &mdash; The error that was thrown.
79- **retry:** `() => Promise<void>` &mdash; A function that will rerender the route component.
80
81</APIBox>
82
83<APIBox header="ErrorBoundary">
84
85You can also use the default `ErrorBoundary` component for a quick UI:
86
87```js app/home.tsx
88// Re-export the default UI
89export { ErrorBoundary } from 'expo-router';
90```
91
92</APIBox>
93
94### Work in progress
95
96React Native LogBox needs to be presented less aggressively to develop with errors. Currently, it shows for `console.error` and `console.warn`. However, it should ideally only show for uncaught errors.
97