agentsclimarketplace

Error handling

Skill lennney/gate-all-skills/skills/website/error-handling

Frontend/Next.js Claude Code Skills — curated + custom

Install
npx -y skills add lennney/gate-all-skills --skill error-handling

Assembled 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 TypeUser MessageAction
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
ValidationSpecific field error messageFix 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.tsx boundary
  • 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.tsx exists (catches root layout errors)
  • Errors are logged server-side for debugging
  • Retry/reset mechanisms available for recoverable errors
  • No raw error.message exposed in production

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.