Error handling
Frontend/Next.js Claude Code Skills — curated + custom
npx -y skills add lennney/gate-all-skills --skill error-handlingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Frontend error handling patterns for Next.js — error boundaries, API error display, form validation errors, and global error recovery strategies. Use when implementing error states, debugging error UI, or designing error recovery flows.
SKILL.md
4.9 KB, as published. Nobody here has run it
Frontend Error Handling (Next.js)
Systematic approach to error handling in Next.js applications.
Error Boundary Hierarchy
Next.js provides built-in error boundaries at every route segment level:
app/
├── error.tsx ← Global error boundary (wraps entire app)
├── layout.tsx
├── dashboard/
│ ├── error.tsx ← Dashboard-specific error boundary
│ ├── page.tsx
│ └── settings/
│ ├── error.tsx ← Settings-specific error boundary
│ └── page.tsx
Root Error Boundary (app/error.tsx)
'use client'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div role="alert">
<h1>Something went wrong</h1>
<p>We've been notified. Please try again.</p>
<button onClick={() => reset()}>Try again</button>
{/* In dev: show error.message for debugging */}
{process.env.NODE_ENV === 'development' && (
<pre>{error.message}</pre>
)}
</div>
)
}
Segment Error Boundary (app/dashboard/error.tsx)
'use client'
export default function DashboardError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div className="p-6 rounded-lg border border-red-200 bg-red-50" role="alert">
<h2>Dashboard unavailable</h2>
<p>{error.message || 'Failed to load dashboard data'}</p>
<button onClick={() => reset()}>Retry</button>
</div>
)
}
Server Action Error Handling
'use server'
export async function createPost(formData: FormData) {
try {
const title = formData.get('title')
if (!title || typeof title !== 'string') {
return { error: 'Title is required' }
}
if (title.length < 3) {
return { error: 'Title must be at least 3 characters' }
}
await db.post.create({ title })
return { success: true }
} catch (e) {
console.error('createPost failed:', e)
return { error: 'Failed to create post. Please try again.' }
}
}
// Client-side handling
'use client'
export function PostForm() {
const [state, formAction, pending] = useActionState(createPost, null)
return (
<form action={formAction}>
<input name="title" aria-invalid={state?.error ? true : undefined} />
{state?.error && <p role="alert" className="text-red-500">{state.error}</p>}
<button disabled={pending}>{pending ? 'Creating...' : 'Create'}</button>
</form>
)
}
API / Fetch Error Handling
// lib/fetch.ts — unified fetch wrapper
export async function apiFetch<T>(
url: string,
options?: RequestInit
): Promise<{ data: T | null; error: string | null }> {
try {
const res = await fetch(url, options)
if (!res.ok) {
const body = await res.json().catch(() => ({}))
return { data: null, error: body.message || `Request failed (${res.status})` }
}
return { data: await res.json(), error: null }
} catch (e) {
return { data: null, error: 'Network error. Please check your connection.' }
}
}
Global Error Handling
global-error.tsx (Root fallback)
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<div role="alert">
<h1>Critical error</h1>
<button onClick={() => reset()}>Reload page</button>
</div>
</body>
</html>
)
}
User-Facing Error Messages
| Error Type | User Message | Action |
|---|---|---|
| Network offline | "You appear to be offline" | Retry button |
| Server error (5xx) | "Our servers are busy. Please try again." | Retry button |
| Not found (404) | "This page doesn't exist" | Go home link |
| Validation | Specific field error message | Fix input |
| Rate limited | "Too many requests. Please wait." | Countdown timer |
| Auth expired | "Your session has expired" | Login button |
Checklist
- Every route segment has an
error.tsxboundary - Server Actions return structured
{ data, error }objects (never throw on expected errors) - API fetch calls have a wrapper with consistent error typing
- Error messages are user-friendly, not raw error objects
- Forms show inline validation with
role="alert" -
global-error.tsxexists (catches root layout errors) - Errors are logged server-side for debugging
- Retry/reset mechanisms available for recoverable errors
- No raw
error.messageexposed in production