Error Handling Prompt Templates
AI prompt templates for error handling. Implement robust exception management and error recovery.
Overview
Error handling separates solid applications from fragile ones. These prompts help you design error handling strategies that catch failures gracefully, provide useful feedback to users and developers, and enable recovery when possible. The goal is code that fails predictably and informatively, not silently or catastrophically.
Best Practices
Describe the types of errors you expect (validation, network, business logic) so handling can be specific
Specify your target audience for error messages, developers need stack traces, users need friendly messages
Include your current error handling patterns so new code stays consistent
Mention whether errors should be recoverable or terminal for your use case
Consider logging, monitoring, and alerting needs alongside the error handling code
Prompt Templates
1. Error Handling Strategy
Design an error handling strategy for this code/feature: **Context:** - Application type: [WEB APP / API / CLI / LIBRARY] - Language/Framework: [LANGUAGE AND FRAMEWORK] - Feature: [WHAT THE CODE DOES] **Error types to handle:** - [ERROR TYPE 1 - e.g. validation errors] - [ERROR TYPE 2 - e.g. network failures] - [ERROR TYPE 3 - e.g. business rule violations] **Error consumers:** - End users: [WHAT THEY SHOULD SEE] - Developers: [WHAT THEY NEED FOR DEBUGGING] - Monitoring: [WHAT TO LOG/ALERT ON] **Current code (if exists):** ```[LANGUAGE] [PASTE RELEVANT CODE] ``` **Provide:** 1. Error classification scheme 2. Custom error classes/types if needed 3. Error handling patterns for each error type 4. User-facing message strategy 5. Logging and monitoring approach
Application: REST API for e-commerce Language: Node.js/Express Feature: Order checkout process Error types: Validation (bad input), Payment failures, Inventory issues, External service timeouts Users see: Friendly messages with action steps Developers need: Full context for debugging Monitoring: Alert on payment failures and service timeouts
## Error Handling Strategy: Order Checkout
### 1. Error Classification
```typescript
// Base error class
export class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number,
public isOperational: boolean = true,
public context?: Record<string, unknown>
) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
// Specific error types
export class ValidationError extends AppError {
constructor(message: string, public fields: FieldError[]) {
super(message, 'VALIDATION_ERROR', 400, true, { fields });
}
}
export class PaymentError extends AppError {
constructor(message: string, public declineCode?: string) {
super(message, 'PAYMENT_FAILED', 402, true, { declineCode });
}
}
export class InventoryError extends AppError {
constructor(message: string, public productId: string, public available: number) {
super(message, 'INSUFFICIENT_INVENTORY', 409, true, { productId, available });
}
}
export class ExternalServiceError extends AppError {
constructor(service: string, originalError: Error) {
super(
`External service failure: ${service}`,
'EXTERNAL_SERVICE_ERROR',
503,
true,
{ service, originalMessage: originalError.message }
);
}
}
```
### 2. Error Handling Patterns
```typescript
// Checkout service with structured error handling
export class CheckoutService {
async processCheckout(order: OrderInput): Promise<Order> {
// Validation errors - fail fast
const validation = this.validateOrder(order);
if (!validation.valid) {
throw new ValidationError('Invalid order data', validation.errors);
}
// Inventory check - recoverable if user adjusts
for (const item of order.items) {
const available = await this.inventory.getAvailable(item.productId);
if (available < item.quantity) {
throw new InventoryError(
`Insufficient stock for ${item.productId}`,
item.productId,
available
);
}
}
// Payment - may require user action
try {
const payment = await this.paymentService.charge(order);
if (!payment.success) {
throw new PaymentError(
'Payment was declined',
payment.declineCode
);
}
} catch (error) {
if (error instanceof PaymentError) throw error;
// Wrap unexpected payment errors
throw new ExternalServiceError('payment-processor', error);
}
// External service calls - wrap with timeout and retry
try {
await this.withRetry(() => this.shippingService.createLabel(order));
} catch (error) {
throw new ExternalServiceError('shipping-service', error);
}
return this.orderRepository.save(order);
}
private async withRetry<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
for (let i = 0; i < attempts; i++) {
try {
return await fn();
} catch (error) {
if (i === attempts - 1) throw error;
await this.delay(Math.pow(2, i) * 1000); // Exponential backoff
}
}
throw new Error('Retry failed');
}
}
```
### 3. Express Error Middleware
```typescript
// Global error handler
export function errorHandler(
error: Error,
req: Request,
res: Response,
next: NextFunction
) {
// Log all errors with context
const logContext = {
requestId: req.id,
method: req.method,
path: req.path,
userId: req.user?.id,
error: {
name: error.name,
message: error.message,
stack: error.stack...(error instanceof AppError && { code: error.code, context: error.context })
}
};
if (error instanceof AppError) {
// Operational error - expected, log as warning
logger.warn('Operational error', logContext);
// Alert on specific error types
if (error instanceof PaymentError || error instanceof ExternalServiceError) {
alerting.notify('checkout-error', logContext);
}
return res.status(error.statusCode).json({
error: {
code: error.code,
message: this.getUserMessage(error)...(error instanceof ValidationError && { fields: error.fields })...(error instanceof InventoryError && {
available: error.available,
productId: error.productId
})
}
});
}
// Unexpected error - log as error, return generic message
logger.error('Unexpected error', logContext);
alerting.page('unexpected-error', logContext); // Wake someone up
return res.status(500).json({
error: {
code: 'INTERNAL_ERROR',
message: 'Something went wrong. Please try again or contact support.',
requestId: req.id // For support tickets
}
});
}
// User-friendly messages
function getUserMessage(error: AppError): string {
const messages: Record<string, string> = {
VALIDATION_ERROR: 'Please check your information and try again.',
PAYMENT_FAILED: 'Your payment could not be processed. Please try a different payment method.',
INSUFFICIENT_INVENTORY: 'Some items in your cart are no longer available in the requested quantity.',
EXTERNAL_SERVICE_ERROR: 'We\'re experiencing technical difficulties. Please try again in a few minutes.'
};
return messages[error.code] || 'An error occurred. Please try again.';
}
```
### 4. Frontend Error Handling
```typescript
// API client with error normalization
async function checkout(order: OrderInput): Promise<Order> {
try {
const response = await api.post('/checkout', order);
return response.data;
} catch (error) {
if (error.response) {
const { code, message, fields } = error.response.data.error;
switch (code) {
case 'VALIDATION_ERROR':
// Show field-level errors
throw new ValidationError(message, fields);
case 'INSUFFICIENT_INVENTORY':
// Prompt user to update cart
throw new InventoryError(message, error.response.data.error);
case 'PAYMENT_FAILED':
// Show payment retry UI
throw new PaymentError(message);
default:
// Generic error with retry option
throw new CheckoutError(message);
}
}
// Network error
throw new NetworkError('Unable to connect. Please check your internet connection.');
}
}
```
### 5. Monitoring & Alerting
| Error Type | Log Level | Alert |
|------------|-----------|-------|
| ValidationError | warn | No (user error) |
| PaymentError | warn | Yes (Slack) if rate >5% |
| InventoryError | warn | No (expected) |
| ExternalServiceError | error | Yes (PagerDuty) |
| Unexpected errors | error | Yes (PagerDuty) |When designing error handling for new features, standardizing across a codebase, or improving existing error handling
- •Distinguish operational errors (expected) from programmer errors (bugs), handle them differently
- •Include request IDs in error responses so users can reference them in support tickets
2. Try-Catch Improvement
Improve the error handling in this code: ```[LANGUAGE] [PASTE CODE WITH POOR ERROR HANDLING] ``` **Current problems:** - [PROBLEM 1 - e.g. catching all errors generically] - [PROBLEM 2 - e.g. swallowing errors silently] **Requirements:** - [WHAT SHOULD HAPPEN ON EACH ERROR TYPE] - [LOGGING REQUIREMENTS] - [USER FEEDBACK REQUIREMENTS] **Provide:** 1. Improved code with proper error handling 2. Explanation of what changed and why 3. Any custom error types needed
Language: Python Code: Function that reads config, calls API, saves to database Problems: Single try/catch around everything, generic 'Error occurred' message, no logging Requirements: Different handling for file errors vs API errors vs DB errors, log errors with context, return specific error messages
## Improved Error Handling
### Before (problematic)
```python
def sync_user_data(user_id):
try:
config = load_config('config.json')
data = fetch_from_api(config['api_url'], user_id)
save_to_database(data)
return {'success': True}
except:
return {'success': False, 'error': 'Error occurred'}
```
### After (improved)
```python
import logging
from dataclasses import dataclass
from typing import Optional
logger = logging.getLogger(__name__)
# Custom exceptions for each error category
class ConfigError(Exception):
"""Configuration file errors."""
pass
class APIError(Exception):
"""External API errors."""
def __init__(self, message: str, status_code: Optional[int] = None):
super().__init__(message)
self.status_code = status_code
class DatabaseError(Exception):
"""Database operation errors."""
pass
@dataclass
class SyncResult:
success: bool
error_code: Optional[str] = None
error_message: Optional[str] = None
user_message: Optional[str] = None
def sync_user_data(user_id: str) -> SyncResult:
"""
Sync user data from external API to database.
Returns SyncResult with success status and error details if failed.
"""
# Step 1: Load configuration
try:
config = load_config('config.json')
except FileNotFoundError:
logger.error("Config file not found", extra={'user_id': user_id})
return SyncResult(
success=False,
error_code='CONFIG_NOT_FOUND',
error_message='Configuration file missing',
user_message='Service is misconfigured. Please contact support.'
)
except json.JSONDecodeError as e:
logger.error("Config file invalid JSON", extra={'user_id': user_id, 'error': str(e)})
return SyncResult(
success=False,
error_code='CONFIG_INVALID',
error_message=f'Configuration parse error: {e}',
user_message='Service is misconfigured. Please contact support.'
)
# Step 2: Fetch from API
try:
data = fetch_from_api(config['api_url'], user_id)
except requests.Timeout:
logger.warning("API timeout", extra={'user_id': user_id, 'url': config['api_url']})
return SyncResult(
success=False,
error_code='API_TIMEOUT',
error_message='API request timed out',
user_message='The service is taking too long. Please try again.'
)
except requests.HTTPError as e:
logger.error("API HTTP error", extra={
'user_id': user_id,
'status_code': e.response.status_code,
'response': e.response.text[:500]
})
if e.response.status_code == 404:
return SyncResult(
success=False,
error_code='USER_NOT_FOUND',
error_message=f'User {user_id} not found in external system',
user_message='Your account was not found. Please verify your information.'
)
return SyncResult(
success=False,
error_code='API_ERROR',
error_message=f'API returned {e.response.status_code}',
user_message='Unable to fetch your data. Please try again later.'
)
except requests.RequestException as e:
logger.error("API connection error", extra={'user_id': user_id, 'error': str(e)})
return SyncResult(
success=False,
error_code='API_CONNECTION_ERROR',
error_message=str(e),
user_message='Unable to connect to external service. Please try again.'
)
# Step 3: Save to database
try:
save_to_database(data)
except IntegrityError as e:
logger.error("Database integrity error", extra={'user_id': user_id, 'error': str(e)})
return SyncResult(
success=False,
error_code='DB_INTEGRITY_ERROR',
error_message=f'Data conflict: {e}',
user_message='There was a conflict saving your data. Please contact support.'
)
except OperationalError as e:
logger.error("Database connection error", extra={'user_id': user_id, 'error': str(e)})
return SyncResult(
success=False,
error_code='DB_CONNECTION_ERROR',
error_message=str(e),
user_message='Database temporarily unavailable. Please try again.'
)
logger.info("User data synced successfully", extra={'user_id': user_id})
return SyncResult(success=True)
```
### What Changed
| Before | After | Why |
|--------|-------|-----|
| Bare `except:` | Specific exception types | Catch only what you can handle |
| Generic error message | Error codes + user messages | Actionable for users and debugging |
| No logging | Structured logging with context | Enables debugging and monitoring |
| Returns dict | Returns dataclass | Type safety, clear contract |
| All-or-nothing | Fail at each step independently | Identify exactly where failure occurred |When improving existing code with poor error handling, code review feedback, or debugging mysterious failures
- •Never use bare 'except:' or 'catch (Exception e)' unless you re-raise, it hides bugs
- •Separate error messages for developers (detailed) from users (actionable, no internals)
3. Retry Logic Implementation
Implement retry logic for this operation: **Operation:** ```[LANGUAGE] [PASTE CODE THAT NEEDS RETRY] ``` **Requirements:** - Retry on: [WHICH ERRORS SHOULD TRIGGER RETRY] - Don't retry on: [WHICH ERRORS SHOULD FAIL IMMEDIATELY] - Max attempts: [NUMBER] - Backoff strategy: [FIXED / EXPONENTIAL / JITTER] - Timeout: [PER-ATTEMPT AND TOTAL] **Provide:** 1. Retry implementation 2. Configuration options 3. Logging for observability 4. Example usage
Operation: HTTP API call to payment processor Retry on: 5xx errors, timeouts, connection errors Don't retry on: 4xx errors (client errors), invalid input Max attempts: 3 Backoff: Exponential with jitter Timeout: 10s per attempt, 30s total
## Retry Logic Implementation
```typescript
import { setTimeout } from 'timers/promises';
// Configuration
interface RetryConfig {
maxAttempts: number;
baseDelayMs: number;
maxDelayMs: number;
timeoutMs: number;
totalTimeoutMs: number;
jitter: boolean;
}
const DEFAULT_CONFIG: RetryConfig = {
maxAttempts: 3,
baseDelayMs: 1000,
maxDelayMs: 10000,
timeoutMs: 10000,
totalTimeoutMs: 30000,
jitter: true,
};
// Errors that should trigger retry
function isRetryable(error: unknown): boolean {
if (error instanceof ApiError) {
// Retry on 5xx (server errors) and specific network errors
return (
error.statusCode >= 500 ||
error.code === 'ETIMEDOUT' ||
error.code === 'ECONNRESET' ||
error.code === 'ECONNREFUSED'
);
}
// Network errors without response
if (error instanceof TypeError && error.message.includes('fetch')) {
return true;
}
return false;
}
// Exponential backoff with jitter
function calculateDelay(attempt: number, config: RetryConfig): number {
// Exponential: 1s, 2s, 4s, 8s...
const exponentialDelay = config.baseDelayMs * Math.pow(2, attempt);
const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);
if (config.jitter) {
// Add random jitter: 50-150% of calculated delay
return cappedDelay * (0.5 + Math.random());
}
return cappedDelay;
}
// Main retry function
async function withRetry<T>(
operation: () => Promise<T>,
config: Partial<RetryConfig> = {}
): Promise<T> {
const finalConfig = {...DEFAULT_CONFIG...config };
const startTime = Date.now();
let lastError: Error;
for (let attempt = 0; attempt < finalConfig.maxAttempts; attempt++) {
// Check total timeout
const elapsed = Date.now() - startTime;
if (elapsed >= finalConfig.totalTimeoutMs) {
throw new RetryExhaustedError(
`Total timeout exceeded after ${elapsed}ms`,
attempt,
lastError
);
}
try {
// Execute with per-attempt timeout
const result = await Promise.race([
operation(),
rejectAfterTimeout(finalConfig.timeoutMs)
]);
// Success - log if it took retries
if (attempt > 0) {
logger.info('Operation succeeded after retry', {
attempts: attempt + 1,
totalTime: Date.now() - startTime
});
}
return result;
} catch (error) {
lastError = error as Error;
// Log the failure
logger.warn('Operation failed', {
attempt: attempt + 1,
maxAttempts: finalConfig.maxAttempts,
error: error.message,
willRetry: isRetryable(error) && attempt < finalConfig.maxAttempts - 1
});
// Don't retry non-retryable errors
if (!isRetryable(error)) {
throw error;
}
// Don't delay after last attempt
if (attempt < finalConfig.maxAttempts - 1) {
const delay = calculateDelay(attempt, finalConfig);
logger.debug(`Waiting ${delay}ms before retry`);
await setTimeout(delay);
}
}
}
// All retries exhausted
throw new RetryExhaustedError(
`Operation failed after ${finalConfig.maxAttempts} attempts`,
finalConfig.maxAttempts,
lastError
);
}
// Timeout helper
function rejectAfterTimeout(ms: number): Promise<never> {
return new Promise((_, reject) => {
setTimeout(() => reject(new TimeoutError(`Operation timed out after ${ms}ms`)), ms);
});
}
// Custom error for exhausted retries
class RetryExhaustedError extends Error {
constructor(
message: string,
public attempts: number,
public lastError: Error
) {
super(message);
this.name = 'RetryExhaustedError';
}
}
```
### Usage Example
```typescript
// Payment processor call with retry
async function chargePayment(paymentData: PaymentInput): Promise<PaymentResult> {
return withRetry(
async () => {
const response = await fetch('https://api.payment.com/charge', {
method: 'POST',
body: JSON.stringify(paymentData),
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
if (!response.ok) {
const error = new ApiError(`Payment API error: ${response.status}`);
error.statusCode = response.status;
throw error;
}
return response.json();
},
{
maxAttempts: 3,
baseDelayMs: 1000,
timeoutMs: 10000,
totalTimeoutMs: 30000
}
);
}
// Usage in application
try {
const result = await chargePayment({ amount: 1000, currency: 'USD' });
console.log('Payment succeeded:', result);
} catch (error) {
if (error instanceof RetryExhaustedError) {
console.error('Payment failed after all retries:', error.lastError);
} else {
// Non-retryable error (4xx, validation)
console.error('Payment failed (not retriable):', error);
}
}
```
### Backoff Visualization
```
Attempt 1: Immediate
Attempt 2: ~1.0-1.5s delay (1s × 2^0 × jitter)
Attempt 3: ~2.0-3.0s delay (1s × 2^1 × jitter)
(Would be) Attempt 4: ~4.0-6.0s delay (1s × 2^2 × jitter)
Total max time: ~6-10s + operation time
```When calling external services, APIs, or any operation with transient failures
- •Always add jitter to prevent thundering herd when many clients retry simultaneously
- •Make retryable vs. non-retryable explicit, retrying 400 Bad Request is pointless
4. Error Boundary Design
Design error boundaries for this application: **Application structure:** ``` [DESCRIBE OR DIAGRAM APP STRUCTURE] ``` **Framework:** [REACT / VUE / ANGULAR / BACKEND SERVICE] **Error sources:** - [SOURCE 1 - e.g. API calls] - [SOURCE 2 - e.g. User input] - [SOURCE 3 - e.g. Third-party scripts] **Fallback requirements:** - [WHAT TO SHOW WHEN ERRORS OCCUR] - [WHAT FUNCTIONALITY TO PRESERVE] **Provide:** 1. Error boundary placement strategy 2. Fallback UI components 3. Error reporting integration 4. Recovery mechanisms
Application: React dashboard with multiple independent widgets Structure: Layout > Sidebar + MainContent > Multiple Widget components Error sources: Each widget fetches its own data, some use third-party charts Fallbacks: Failed widget shows error message, rest of dashboard stays functional
## Error Boundary Strategy
### Boundary Placement
```
┌─────────────────────────────────────────────────────────────┐
│ AppErrorBoundary (catches fatal errors, shows full-page) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Layout │ │
│ │ ┌─────────┐ ┌─────────────────────────────────────────┐ │ │
│ │ │Sidebar │ │ MainContent │ │ │
│ │ │(no │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │boundary │ │ │ WidgetGrid │ │ │ │
│ │ │- static)│ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │
│ │ │ │ │ │ │WidgetError│ │WidgetError│ │ │ │ │
│ │ │ │ │ │ │ Boundary │ │ Boundary │ │ │ │ │
│ │ │ │ │ │ │┌─────────┐│ │┌─────────┐│ │ │ │ │
│ │ │ │ │ │ ││ Widget ││ ││ Widget ││ │ │ │ │
│ │ │ │ │ │ │└─────────┘│ │└─────────┘│ │ │ │ │
│ │ │ │ │ │ └───────────┘ └───────────┘ │ │ │ │
│ │ └─────────┘ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### Implementation
```tsx
// 1. Reusable Error Boundary Component
import { Component, ErrorInfo, ReactNode } from 'react';
import * as Sentry from '@sentry/react';
interface Props {
children: ReactNode;
fallback?: ReactNode | ((error: Error, retry: () => void) => ReactNode);
onError?: (error: Error, errorInfo: ErrorInfo) => void;
level?: 'widget' | 'section' | 'app';
}
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) {
// Report to error tracking
Sentry.captureException(error, {
contexts: {
react: { componentStack: errorInfo.componentStack }
},
tags: { boundary_level: this.props.level || 'unknown' }
});
// Custom error handler
this.props.onError?.(error, errorInfo);
}
retry = () => {
this.setState({ hasError: false, error: null });
};
render() {
if (this.state.hasError) {
// Custom fallback or default
if (typeof this.props.fallback === 'function') {
return this.props.fallback(this.state.error!, this.retry);
}
if (this.props.fallback) {
return this.props.fallback;
}
// Default fallback based on level
return <DefaultFallback level={this.props.level} onRetry={this.retry} />;
}
return this.props.children;
}
}
// 2. Level-specific fallbacks
function DefaultFallback({ level, onRetry }: { level?: string; onRetry: () => void }) {
switch (level) {
case 'widget':
return (
<div className="widget-error p-4 bg-gray-50 rounded-lg text-center">
<AlertCircle className="mx-auto h-8 w-8 text-gray-400" />
<p className="mt-2 text-sm text-gray-600">Unable to load this widget</p>
<button
onClick={onRetry}
className="mt-2 text-sm text-blue-600 hover:underline"
>
Try again
</button>
</div>
);
case 'section':
return (
<div className="section-error p-8 text-center">
<h3 className="text-lg font-medium">Something went wrong</h3>
<p className="mt-1 text-gray-600">This section couldn't be loaded.</p>
<button onClick={onRetry} className="mt-4 btn btn-secondary">
Retry
</button>
</div>
);
case 'app':
default:
return (
<div className="app-error min-h-screen flex items-center justify-center">
<div className="text-center">
<h1 className="text-2xl font-bold">Something went wrong</h1>
<p className="mt-2 text-gray-600">
We've been notified and are working on a fix.
</p>
<button
onClick={() => window.location.reload()}
className="mt-4 btn btn-primary"
>
Refresh page
</button>
</div>
</div>
);
}
}
```
### Usage in Dashboard
```tsx
// App.tsx - Top level boundary
function App() {
return (
<ErrorBoundary level="app">
<Dashboard />
</ErrorBoundary>
);
}
// Dashboard.tsx - Widget-level boundaries
function Dashboard() {
const widgets = useWidgets();
return (
<Layout>
<WidgetGrid>
{widgets.map((widget) => (
<ErrorBoundary
key={widget.id}
level="widget"
fallback={(error, retry) => (
<WidgetErrorCard
widgetName={widget.name}
error={error}
onRetry={retry}
/>
)}
onError={(error) => {
// Track which widget failed
analytics.track('widget_error', {
widget_id: widget.id,
error: error.message
});
}}
>
<WidgetRenderer widget={widget} />
</ErrorBoundary>
))}
</WidgetGrid>
</Layout>
);
}
// Widget with data fetching error handling
function WidgetRenderer({ widget }: { widget: Widget }) {
const { data, error, isLoading, refetch } = useQuery({
queryKey: ['widget', widget.id],
queryFn: () => fetchWidgetData(widget.id),
retry: 2, // React Query handles data fetching retries
});
// Data loading errors (different from render errors)
if (error) {
return (
<WidgetLoadError
message="Failed to load data"
onRetry={refetch}
/>
);
}
if (isLoading) return <WidgetSkeleton />;
// This may throw during render - caught by ErrorBoundary
return <widget.component data={data} />;
}
```
### Error Recovery Patterns
| Error Type | Recovery Strategy |
|------------|-------------------|
| Data fetch failed | Show error in widget, retry button, other widgets unaffected |
| Render error | ErrorBoundary catches, shows fallback, retry resets component |
| Third-party script | Boundary isolates, widget shows placeholder |
| Fatal app error | Full-page error, suggest refresh |When building UIs with independent components that shouldn't crash the entire application
- •Place boundaries at natural isolation points, if a widget failing shouldn't break the dashboard, it needs its own boundary
- •Distinguish data fetching errors (handle in component) from render errors (handle in boundary)
Common Mistakes to Avoid
Catching all exceptions generically, hides bugs and makes debugging difficult
Showing internal error details to users, security risk and poor UX
Not logging errors with enough context, makes production debugging impossible
Frequently Asked Questions
Error handling separates solid applications from fragile ones. These prompts help you design error handling strategies that catch failures gracefully, provide useful feedback to users and developers, and enable recovery when possible. The goal is code that fails predictably and informatively, not silently or catastrophically.
Related Templates
Code Review Prompt Templates
AI prompt templates for thorough code reviews. Get comprehensive feedback on code quality, security, and best practices.
Debugging Prompt Templates
AI prompt templates for debugging code. Identify issues, understand errors, and find solutions faster.
Code Documentation Prompt Templates
AI prompt templates for writing code documentation. Create clear comments, READMEs, and API docs.
Have your own prompt to optimize?