Open jviall opened 10 months ago
The Legacy react docs mention that Server Rendering errors aren't caught by error boundaries, but this note was removed in the new React docs--has this changed?
Note Error boundaries do not catch errors for: Event handlers (learn more) Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks) Server side rendering Errors thrown in the error boundary itself (rather than its children)
This discussion topic seems to target the same issue https://github.com/vercel/next.js/discussions/53618
Using App Router -- currently it's possible to catch server-side errors like this:
import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
const ThisWillFail = async () => {
// If this request fails I want the <ErrorBoundary> to catch it, rather than having
// the whole page fails and fallback to `error.tsx`.
const data = fetch('https://somepage.com/api');
return <div>Hello</div>;
}
const Thing = () => (
<ErrorBoundary fallback={<div>An error happened</div>}>
<Suspense fallback={<div>Loading...</div>}>
<ThisWillFail />
</Suspense>
</ErrorBoundary>
);
export default Thing;
However, if I want to display the actual error message to the user (ie. use the FallbackComponent
prop instead of the fallback
prop on <ErrorBoundary>
) there are some problems. I want this:
import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
const ThisWillFail = async () => {
// If this request fails I want the <ErrorBoundary> to catch it, rather than having
// the whole page fails and fallback to `error.tsx`.
const data = fetch('https://somepage.com/api');
return <div>Hello</div>;
}
const ErrorHandler = ({error}) => {
return <div>{error.message}</div>
}
const Thing = () => (
<ErrorBoundary FallbackComponent={ErrorHandler}>
<Suspense fallback={<div>Loading...</div>}>
<ThisWillFail />
</Suspense>
</ErrorBoundary>
);
export default Thing;
FallbackComponent
causes this failure in Next.js: Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
. use client
at the top of the file. But that causes the whole app to go into an infinite rendering loop where (for some reason) the error is caught, but then the whole app re-renders, fails again, gets caught, gets re-rendered, etc...The Next.js Error Handling documentation mentions using ErrorBoundary
but doesn't provide any examples of how to do it.
Any help would be appreciated here.
- I can get around that error by putting
use client
at the top of the file. But that causes the whole app to go into an infinite rendering loop where (for some reason) the error is caught, but then the whole app re-renders, fails again, gets caught, gets re-rendered, etc...
looks like no infinite loops for now. works form me fine the way you described
@EvHaus thanks a lot for your answer. Your proposition is working for me on Next 14.1.4
Can you share more details on why ErrorBoundary
and Suspense
must be o the same component level to make it work?
Previously I was trying to use my ErrorBoundary
1 level below my Suspense
and it was not working.
Don't know if I am an edge case, but it's very frustrating that Vercel provides poor documentation about how to handle RSC errors.
@th91vi Sorry, I don't know. That's why this issue exists. :) Need Next.js devs to help us.
@EvHaus
Note that using <Suspense>
here is probably not the desired behavior for most people looking to catch errors in server components.
Correct me if I'm wrong, but don't forget that suspense will shift part of the server rendering to a second time and display a fallback to the client in the meantime.
Link to the code that reproduces this issue
https://codesandbox.io/p/devbox/nextjs-error-boundary-catches-server-throws-mmvlsd
To Reproduce
ErrorBoundary
component<ErrorBoundary />
with some arbitrary fallback UICurrent vs. Expected behavior
Current Behavior: any custom
<ErrorBoundary />
component will not catch an error that is thrown from a descendent server component, instead it will be uncaught, unless aerror.tsx
file is defined somewhere for the given route.Expected Behavior:
<ErrorBoundary />
-like components should catch server errors without needing to be implemented as Route Segmenterror.tsx
files.Verify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
App Router
Additional context
In the linked sandbox, adding
"use client";
to the<BadComponent />
resolves the issue, proving the gap in functionality between Next's proprietary error boundary and how "native" error boundaries behave. I also don't believe this discrepancy has always been the case.