error-boundary-generator
npx machina-cli add skill Nembie/claude-code-skills/error-boundary-generator --openclawError Boundary Generator
Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.
Process
- Scan the React component tree and identify components that need error boundaries.
- For each gap, generate an error boundary with a typed fallback component.
- For Next.js App Router, generate
error.tsxandloading.tsxfiles where missing.
Identification Rules
Scan for components that:
- Fetch data: contain
fetch(),useQuery,useSWR, server componentasyncfunctions, or Prisma calls - Use external services: Stripe, auth providers, third-party SDKs
- Have complex state logic:
useReducerwith many cases, complexuseEffectchains - Render user-generated content:
dangerouslySetInnerHTML, rich text renderers, markdown parsers - Are page-level route components:
page.tsxfiles in Next.js App Router
Error Types
Generate different fallback UIs based on error type:
Recoverable Errors (retry button)
For data fetching failures, network errors, timeout errors:
"use client";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error(error);
}, [error]);
return (
<div role="alert">
<h2>Something went wrong</h2>
<p>We couldn't load this content. Please try again.</p>
<button onClick={reset}>Try again</button>
</div>
);
}
Auth Errors (redirect to login)
For 401/403 responses detected in the error:
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
export default function Error({ error }: { error: Error }) {
const router = useRouter();
useEffect(() => {
if (error.message.includes("401") || error.message.includes("Unauthorized")) {
router.push("/login");
}
}, [error, router]);
return (
<div role="alert">
<h2>Access denied</h2>
<p>Please sign in to view this page.</p>
<button onClick={() => router.push("/login")}>Sign in</button>
</div>
);
}
Not Found (404 UI)
Generate not-found.tsx for dynamic routes:
import Link from "next/link";
export default function NotFound() {
return (
<div>
<h2>Not found</h2>
<p>The requested resource doesn't exist.</p>
<Link href="/">Go home</Link>
</div>
);
}
Server Errors (500 UI)
For global-error.tsx at the app root:
"use client";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<div role="alert">
<h2>Something went wrong</h2>
<p>An unexpected error occurred. Please try again or contact support.</p>
{error.digest && <p>Error reference: {error.digest}</p>}
<button onClick={reset}>Try again</button>
</div>
</body>
</html>
);
}
Component-Level Error Boundaries
For non-Next.js or for wrapping specific components within a page:
"use client";
import { Component, type ErrorInfo, type ReactNode } from "react";
interface Props {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: ErrorInfo) => void;
}
interface State {
hasError: boolean;
error: Error | null;
}
export class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, error: null };
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.props.onError?.(error, errorInfo);
}
render() {
if (this.state.hasError) {
return this.props.fallback ?? (
<div role="alert">
<p>Something went wrong.</p>
<button onClick={() => this.setState({ hasError: false, error: null })}>
Try again
</button>
</div>
);
}
return this.props.children;
}
}
Loading States
Generate loading.tsx alongside error.tsx where missing:
export default function Loading() {
return (
<div role="status" aria-busy="true">
<span>Loading...</span>
</div>
);
}
Output Format
## Error Boundary Report
### Gaps Found
| Location | Risk | Reason | Generated |
|----------|------|--------|-----------|
| app/dashboard/page.tsx | High | Fetches data, no error.tsx | error.tsx + loading.tsx |
| components/PaymentForm.tsx | High | Stripe integration | ErrorBoundary wrapper |
| app/posts/[id]/page.tsx | Medium | Dynamic route | not-found.tsx + error.tsx |
### Files Generated
[List of all generated files with their contents]
Reference
See references/error-patterns.md for error boundary placement strategy, Next.js error hierarchy, and logging integration patterns.
Source
git clone https://github.com/Nembie/claude-code-skills/blob/main/skills/error-boundary-generator/SKILL.mdView on GitHub Overview
Error Boundary Generator analyzes a React app and creates typed fallback UIs for missing boundaries. It adapts patterns to your configured stack by reading config/defaults.md and, in Next.js App Router projects, can generate error.tsx and loading.tsx when needed.
How This Skill Works
The tool scans the component tree to identify risk factors such as data fetching, external services, complex state logic, user-generated content, and page-level routes. For each gap, it outputs an error boundary with a typed fallback component. In Next.js App Router setups, it creates error.tsx and loading.tsx files if they are missing, aligning with the described error types and UI patterns.
When to Use It
- Guard data-fetching components that may fail (fetch, useQuery, useSWR, Prisma calls) by wrapping them with a boundary and a recoverable fallback.
- Protect components that rely on external services or third-party SDKs to gracefully handle service outages or timeouts.
- Wrap complex state logic (useReducer with many cases or long useEffect chains) to prevent UI crashes from edge cases.
- Wrap components that render user-generated content (dangerouslySetInnerHTML, rich text renderers) to prevent crashes from unsafe input.
- Add or fix Next.js App Router error boundaries by generating missing error.tsx and loading.tsx for page.tsx routes.
Quick Start
- Step 1: Run the analyzer to scan your React/Next.js app and identify components that need error boundaries.
- Step 2: Generate error boundaries around each identified gap with a typed fallback component (recoverable/auth/not-found/server types as appropriate).
- Step 3: If using Next.js App Router, ensure error.tsx and loading.tsx exist for missing boundaries; test by simulating failures in development.
Best Practices
- Wrap only risky components with boundaries rather than the entire page to minimize UI disruption.
- Use typed fallback components to clearly signal the error type and recovery options without exposing internal details.
- Differentiate error types (recoverable, auth, not-found, server) and tailor the UI accordingly (retry, redirect, not-found UI, 500 UI).
- Test error boundaries by simulating failures and validating retry/reset behavior and user redirection where applicable.
- Ensure accessibility and consistency in fallbacks (aria-live regions, clear headings, and actionable controls).
Example Use Cases
- A data list component wrapped with a boundary shows a retry button when a fetch query fails.
- An auth-protected page boundary redirects to /login on 401/403 errors.
- Dynamic routes render a Not Found UI via generated not-found.tsx when the resource is missing.
- Global 500 UI appears at the app root using a GlobalError boundary with an optional error digest.
- A low-level widget is wrapped with an ErrorBoundary to catch rendering issues without crashing the whole page.