Introduction
There are two fundamentally different error types. I call them the soft and the hard error, since one is gonna break the application totally and the other only does unintended things, that arenβt actually breaking anything. In this article I will talk about the differences and how to handle each of them.
Expected Exceptions (Soft)
This error can be expected because itβs part of the normal application flow. They are handled explicit in code with conditional rendering, redirect or notFound components. Common examples could be:
- Missing data or routes
- Invalid input
- Lack of authorization
Handling expected exceptions
Te best way to deal with that issue is to make use of Next.js not-found.tsx component which is usually placed within the route like:
src/app/project/[projectId]/not-found.tsxNow I only need to create my component, here Iβm gonna make use of my own π Placeholder Component to display a custom message:
import Link from "next/link";
import { Placeholder } from "@/components/placeholder";
import { Button } from "@/components/ui/button";
import { ticketsPath } from "@/paths";
export default function NotFound() {
return (
<Placeholder
label="We could not find your ticket"
button={
<Button asChild variant="outline">
<Link href={ticketsPath()}>Go to Tickets</Link>
</Button>
}
/>
);
}
I then can easily call this component whenever an excepted exception occurs, like trying to fetch an missing object from a database.
const TicketPage = async ({ params }: TicketPageProps) => {
if (!ticket) {
notFound(); // Show not-found.tsx
}
return (
//...
);
};
export default TicketPage;Uncaught exceptions (hard)
This errors are unexpected runtime failures that are most likely gonna break the application. They are should be handled by a error.tsx file wich signal that something serious went wrong. Common examples could be:
- Bugs
- System issues
- Failed network/database operations
- Accessing undefined values
Handling uncaught exceptions
The best way to deal with this errors, is to make use of Next.js error.tsx file. When placing the error.tsx file next to the page.tsx file, Next.js will display itβs content to the user and also avoiding the app to crash fully.
Itβs important to mention that these error.tsx file will only work for their subtree. If I want a file that works for the whole application, I should make use of the global-error.tsx file.
src/app/project/error.tsxAnd again I will make use of the π Placeholder Component to display the error message to the user.
"use client";
import { Placeholder } from "@/components/placeholder";
export default function Error({ error }: { error: Error }) {
return <Placeholder label={error.message ?? "Something went wrong!"} />;
}ErrorBoundary
The error.tsx file will replace the whole page.tsx component. If I want more control, I can use the ErrorBoundary to replace only some part of my component. Itβs the same principe like with Loading Components and Suspense.
npm install react-error-boundaryThe ErrorBoundy kinda acts as a try .. catch. It will try to display its children, but if there happens to be an error, it will then display the fallback component. Other components of the same page wonβt be replaced, unlike with the error.tsx file.
<ErrorBoundary fallback={<Placeholder label="Something went wrong!" />}>
<TicketList />
</ErrorBoundary>Conclusion
Errors are always a pain but unfortunately unavoidable. Thankfully Next.js and React offer good solutions for each use case. Hopefully with knowing that, my application will never crash in production - I dream that most likely wonβt come true.