Skip to content

Commit beeb329

Browse files
committed
Update middleware error handling docs
1 parent f90a426 commit beeb329

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

docs/how-to/middleware.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,20 @@ const authMiddleware = async ({ request, context }) => {
191191

192192
### `next()` and Error Handling
193193

194-
`next()` is not designed to throw errors under normal conditions, so you generally shouldn't find yourself wrapping `next` in a `try`/`catch`. The responsibility of the `next()` function is to return a `Response` for the current `Request`, so as long as that can be completed, `next()` will return the Response and won't `throw`. Even if a `loader` throws an error, or a component fails to render, React Router already handles those by rendering the nearest `ErrorBoundary`, so a Response is still generated without issue.
194+
`next()` is not designed to throw errors under normal conditions, so you generally shouldn't find yourself wrapping `next` in a `try`/`catch`. The responsibility of the `next()` function is to return a `Response` for the current `Request`, so as long as that can be completed, `next()` will return the `Response` and won't `throw`. Even if a `loader` throws an error, or a component fails to render, React Router already handles those by rendering the nearest `ErrorBoundary`, so a `Response` is still generated without issue and propagated up through `next()`.
195195

196-
This behavior is important to allow middleware patterns such as automatically setting required headers on outgoing responses (i.e., committing a session) from a root middleware. If any error caused that to throw, we'd miss the execution of ancestor middlewares on the way out and those required headers wouldn't be set.
196+
This behavior is important to allow middleware patterns such as automatically setting required headers on outgoing responses (i.e., committing a session) from a root middleware. If any error from a loader/action/render caused `next()` to `throw`, we'd miss the execution of ancestor middlewares on the way out and those required headers wouldn't be set.
197197

198-
The only cases in which `next()` _should_ throw are if we fail to generate a Response. There's a few ways in which this could happen:
198+
The only cases in which `next()` _should_ throw are if we fail to generate a `Response`. There's a few ways in which this could happen:
199199

200200
- A middleware can short circuit the rest of the request and throw a `Response` (usually a `redirect`)
201201
- If the logic directly inside of a middleware function throws, that will cause the ancestor `next()` function to throw
202202

203+
If a middleware _does_ throw (and is not caught by an ancestor middleware), then ancestor middlewares will be skipped, but React Router will still attempt to render that error in an `ErrorBoundary`.
204+
205+
- If the error threw before `next()` was called, then we don't have `loaderData` for any routes so we'll bubble to the first `ErrorBoundary` at or above all `loader` functions
206+
- If the error threw after `next()` was called, then we will bubble to the nearest `ErrorBoundary` from the throwing route
207+
203208
## Changes to `getLoadContext`/`AppLoadContext`
204209

205210
<docs-info>This only applies if you are using a custom server and a custom `getLoadContext` function</docs-info>

0 commit comments

Comments
 (0)