Get the FREE Ultimate OpenClaw Setup Guide →
npx machina-cli add skill JanSzewczyk/claude-plugins/error-handling --openclaw
Files (1)
SKILL.md
8.0 KB

Error Handling Skill

Comprehensive error handling patterns for Next.js applications.

Reference Files:

Error Handling Philosophy

Principles:

  1. Never expose internal errors to users - Log details server-side, show friendly messages client-side
  2. Use typed errors - DbError class for database, ActionResponse for server actions
  3. Fail gracefully - Error boundaries, fallback UI, retry mechanisms
  4. Log everything - Structured logging with context for debugging
  5. Provide feedback - Toast notifications for user-facing errors

Error Handling Layers

┌─────────────────────────────────────────────────────────────┐
│                    Client Layer                              │
│  • Error Boundaries (React)                                  │
│  • Toast Notifications (user feedback)                       │
│  • Form field errors (inline validation)                     │
└─────────────────────────────────────────────────────────────┘
                              ↑
┌─────────────────────────────────────────────────────────────┐
│                  Server Action Layer                         │
│  • ActionResponse<T> / RedirectAction types                  │
│  • Zod validation with fieldErrors                           │
│  • Toast cookies for redirect feedback                       │
└─────────────────────────────────────────────────────────────┘
                              ↑
┌─────────────────────────────────────────────────────────────┐
│                   Database Layer                             │
│  • DbError class (typed errors)                              │
│  • Tuple pattern [error, data]                               │
│  • categorizeDbError() helper                                │
└─────────────────────────────────────────────────────────────┘
                              ↑
┌─────────────────────────────────────────────────────────────┐
│                   Logging Layer                              │
│  • Pino structured logging                                   │
│  • Error context (errorCode, isRetryable, userId)            │
│  • Log before returning error                                │
└─────────────────────────────────────────────────────────────┘

Quick Reference

Database Layer (DbError)

import { categorizeDbError, DbError } from "~/lib/firebase/errors";

// Tuple pattern - always return [error, data]
export async function getById(
  id: string,
): Promise<[null, Data] | [DbError, null]> {
  if (!id?.trim()) {
    return [DbError.validation("Invalid id"), null];
  }

  try {
    const doc = await db.collection("items").doc(id).get();
    if (!doc.exists) {
      return [DbError.notFound("Item"), null];
    }
    return [null, transform(doc)];
  } catch (error) {
    const dbError = categorizeDbError(error, "Item");
    logger.error({ errorCode: dbError.code, id }, "Database error");
    return [dbError, null];
  }
}

Server Action Layer

import { setToastCookie } from "~/lib/toast/server/toast.cookie";
import type { ActionResponse } from "~/lib/action-types";

export async function createItem(data: FormData): ActionResponse<Item> {
  const { userId } = await auth();
  if (!userId) {
    return { success: false, error: "Unauthorized" };
  }

  // Validation errors - return fieldErrors for form display
  const parsed = schema.safeParse(data);
  if (!parsed.success) {
    return {
      success: false,
      error: "Validation failed",
      fieldErrors: parsed.error.flatten().fieldErrors,
    };
  }

  // Database errors - toast + generic message
  const [error, item] = await createItemInDb(parsed.data);
  if (error) {
    await setToastCookie("Failed to create item", "error");
    return { success: false, error: "Unable to create item" };
  }

  await setToastCookie("Item created!", "success");
  return { success: true, data: item };
}

Client Layer (Error Boundary)

// app/error.tsx - Catches unhandled errors
"use client";

export default function Error({
  error,
  reset
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // Log to error tracking service
    logError(error);
  }, [error]);

  return (
    <div className="error-container">
      <h2>Something went wrong</h2>
      <Button onClick={reset}>Try again</Button>
    </div>
  );
}

DbError Properties

PropertyTypeDescription
codestringError code (validation, not-found, permission-denied, etc.)
messagestringUser-friendly error message
isRetryablebooleanTrue for transient errors (network, timeout)
isNotFoundbooleanTrue when resource doesn't exist
isAlreadyExistsbooleanTrue when creating existing resource
isPermissionDeniedbooleanTrue for auth/permission issues

Static Factory Methods

DbError.notFound("User"); // Resource not found
DbError.alreadyExists("Budget"); // Resource already exists
DbError.validation("Invalid input"); // Validation failed
DbError.dataCorruption("Event"); // Document exists but data invalid
DbError.permissionDenied(); // Auth/permission issue

Error Response Flow

Database Error
    ↓
categorizeDbError() → DbError with properties
    ↓
Log error with context (logger.error)
    ↓
Return tuple [error, null]
    ↓
Server Action checks error properties
    ↓
Set toast cookie for user feedback
    ↓
Return ActionResponse with generic message
    ↓
Client displays toast + handles state

Related Skills

  • firebase-firestore - DbError class and database patterns
  • server-actions - ActionResponse types and patterns
  • toast-notifications - User feedback via toasts
  • structured-logging - Pino logging patterns

Source

git clone https://github.com/JanSzewczyk/claude-plugins/blob/main/plugins/nextjs-react/skills/error-handling/SKILL.mdView on GitHub

Overview

This skill provides comprehensive error handling patterns across database, server actions, React UI, and logging in Next.js apps. It emphasizes typed errors (DbError, ActionResponse), user-facing feedback via toasts, and structured logging to aid debugging and resilience.

How This Skill Works

It defines four layers: Database Layer with DbError, the [error, data] tuple pattern, and categorizeDbError; Server Action Layer with ActionResponse/RedirectAction, Zod fieldErrors, and toast cookies for redirects; Client Layer with React Error Boundaries and toast notifications; and a Logging Layer using Pino for structured logs with error context, logged before returning errors.

When to Use It

  • When a database operation can fail (not found, validation, or server errors) and you want typed, predictable error handling.
  • When server actions can error and you need standardized ActionResponse/RedirectAction patterns.
  • When you require user-facing feedback for errors via toast notifications without exposing internal details.
  • When you must log rich context (errorCode, isRetryable, userId) and avoid leaking internal stack traces.
  • When building resilient UI with error boundaries and fallback UI plus retry mechanisms.

Quick Start

  1. Step 1: Implement DbError and categorizeDbError, and adopt the [null, Data] | [DbError, null] tuple pattern for DB calls.
  2. Step 2: In server actions, use ActionResponse/RedirectAction, apply Zod fieldErrors, and set toast cookies for redirect feedback.
  3. Step 3: On the client, add React error boundaries and toast notifications, and enable structured logging with Pino, including error context.

Best Practices

  • Use typed errors (DbError, ActionResponse) to drive deterministic handling across layers.
  • Return errors using a consistent [error, data] tuple pattern to simplify caller code.
  • Centralize error categorization with categorizeDbError() and log details before returning.
  • Show friendly messages via toast notifications instead of exposing internal error data.
  • Wrap UI components with React error boundaries and provide clear fallback UI and retry options.

Example Use Cases

  • How to handle database errors
  • Error boundary patterns
  • Toast notifications for errors
  • Server action error handling
  • Structured logging with context (errorCode, isRetryable, userId)

Frequently Asked Questions

Add this skill to your agents

Related Skills

Sponsor this space

Reach thousands of developers