10 min read
ā¢Question 39 of 47hardAdvanced Error Handling Patterns
Comprehensive error handling strategies.
Error Handling Patterns
Error Boundary Hierarchy
code.txtTSX
// app/error.tsx - Catches errors in page and children
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Log to error reporting service
reportError(error);
}, [error]);
return (
<div>
<h2>Something went wrong!</h2>
<p>{error.message}</p>
<button onClick={reset}>Try again</button>
</div>
);
}
// app/global-error.tsx - Catches root layout errors
'use client';
export default function GlobalError({ error, reset }) {
return (
<html>
<body>
<h2>Critical Error</h2>
<button onClick={reset}>Reload</button>
</body>
</html>
);
}Server Action Error Handling
code.txtTSX
'use server';
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export async function signUp(formData: FormData) {
try {
const validated = schema.parse({
email: formData.get('email'),
password: formData.get('password'),
});
await createUser(validated);
return { success: true };
} catch (error) {
if (error instanceof z.ZodError) {
return { error: error.errors[0].message };
}
// Don't expose internal errors
return { error: 'An error occurred' };
}
}API Route Error Handling
code.txtTSX
// app/api/users/route.ts
import { NextResponse } from 'next/server';
class APIError extends Error {
constructor(
message: string,
public status: number,
public code: string
) {
super(message);
}
}
export async function GET() {
try {
const users = await getUsers();
return NextResponse.json(users);
} catch (error) {
if (error instanceof APIError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{ status: error.status }
);
}
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}