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` — The error that was thrown. 79- **retry:** `() => Promise<void>` — 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