error-handling-patterns
Master error handling patterns across languages including exceptions, Result types, error propagation, and graceful degradation to build resilient applications. Use when implementing error handling, designing APIs, or improving application reliability.
Install
mkdir -p .claude/skills/error-handling-patterns && curl -L -o skill.zip "https://mcp.directory/api/skills/download/51" && unzip -o skill.zip -d .claude/skills/error-handling-patterns && rm skill.zipInstalls to .claude/skills/error-handling-patterns
About this skill
Error Handling Patterns
Build resilient applications with robust error handling strategies that gracefully handle failures and provide excellent debugging experiences.
When to Use This Skill
- Implementing error handling in new features
- Designing error-resilient APIs
- Debugging production issues
- Improving application reliability
- Creating better error messages for users and developers
- Implementing retry and circuit breaker patterns
- Handling async/concurrent errors
- Building fault-tolerant distributed systems
Core Concepts
1. Error Handling Philosophies
Exceptions vs Result Types:
- Exceptions: Traditional try-catch, disrupts control flow
- Result Types: Explicit success/failure, functional approach
- Error Codes: C-style, requires discipline
- Option/Maybe Types: For nullable values
When to Use Each:
- Exceptions: Unexpected errors, exceptional conditions
- Result Types: Expected errors, validation failures
- Panics/Crashes: Unrecoverable errors, programming bugs
2. Error Categories
Recoverable Errors:
- Network timeouts
- Missing files
- Invalid user input
- API rate limits
Unrecoverable Errors:
- Out of memory
- Stack overflow
- Programming bugs (null pointer, etc.)
Language-Specific Patterns
Python Error Handling
Custom Exception Hierarchy:
class ApplicationError(Exception):
"""Base exception for all application errors."""
def __init__(self, message: str, code: str = None, details: dict = None):
super().__init__(message)
self.code = code
self.details = details or {}
self.timestamp = datetime.utcnow()
class ValidationError(ApplicationError):
"""Raised when validation fails."""
pass
class NotFoundError(ApplicationError):
"""Raised when resource not found."""
pass
class ExternalServiceError(ApplicationError):
"""Raised when external service fails."""
def __init__(self, message: str, service: str, **kwargs):
super().__init__(message, **kwargs)
self.service = service
# Usage
def get_user(user_id: str) -> User:
user = db.query(User).filter_by(id=user_id).first()
if not user:
raise NotFoundError(
f"User not found",
code="USER_NOT_FOUND",
details={"user_id": user_id}
)
return user
Context Managers for Cleanup:
from contextlib import contextmanager
@contextmanager
def database_transaction(session):
"""Ensure transaction is committed or rolled back."""
try:
yield session
session.commit()
except Exception as e:
session.rollback()
raise
finally:
session.close()
# Usage
with database_transaction(db.session) as session:
user = User(name="Alice")
session.add(user)
# Automatic commit or rollback
Retry with Exponential Backoff:
import time
from functools import wraps
from typing import TypeVar, Callable
T = TypeVar('T')
def retry(
max_attempts: int = 3,
backoff_factor: float = 2.0,
exceptions: tuple = (Exception,)
):
"""Retry decorator with exponential backoff."""
def decorator(func: Callable[..., T]) -> Callable[..., T]:
@wraps(func)
def wrapper(*args, **kwargs) -> T:
last_exception = None
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except exceptions as e:
last_exception = e
if attempt < max_attempts - 1:
sleep_time = backoff_factor ** attempt
time.sleep(sleep_time)
continue
raise
raise last_exception
return wrapper
return decorator
# Usage
@retry(max_attempts=3, exceptions=(NetworkError,))
def fetch_data(url: str) -> dict:
response = requests.get(url, timeout=5)
response.raise_for_status()
return response.json()
TypeScript/JavaScript Error Handling
Custom Error Classes:
// Custom error classes
class ApplicationError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500,
public details?: Record<string, any>
) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
class ValidationError extends ApplicationError {
constructor(message: string, details?: Record<string, any>) {
super(message, 'VALIDATION_ERROR', 400, details);
}
}
class NotFoundError extends ApplicationError {
constructor(resource: string, id: string) {
super(
`${resource} not found`,
'NOT_FOUND',
404,
{ resource, id }
);
}
}
// Usage
function getUser(id: string): User {
const user = users.find(u => u.id === id);
if (!user) {
throw new NotFoundError('User', id);
}
return user;
}
Result Type Pattern:
// Result type for explicit error handling
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// Helper functions
function Ok<T>(value: T): Result<T, never> {
return { ok: true, value };
}
function Err<E>(error: E): Result<never, E> {
return { ok: false, error };
}
// Usage
function parseJSON<T>(json: string): Result<T, SyntaxError> {
try {
const value = JSON.parse(json) as T;
return Ok(value);
} catch (error) {
return Err(error as SyntaxError);
}
}
// Consuming Result
const result = parseJSON<User>(userJson);
if (result.ok) {
console.log(result.value.name);
} else {
console.error('Parse failed:', result.error.message);
}
// Chaining Results
function chain<T, U, E>(
result: Result<T, E>,
fn: (value: T) => Result<U, E>
): Result<U, E> {
return result.ok ? fn(result.value) : result;
}
Async Error Handling:
// Async/await with proper error handling
async function fetchUserOrders(userId: string): Promise<Order[]> {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
return orders;
} catch (error) {
if (error instanceof NotFoundError) {
return []; // Return empty array for not found
}
if (error instanceof NetworkError) {
// Retry logic
return retryFetchOrders(userId);
}
// Re-throw unexpected errors
throw error;
}
}
// Promise error handling
function fetchData(url: string): Promise<Data> {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new NetworkError(`HTTP ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error('Fetch failed:', error);
throw error;
});
}
Rust Error Handling
Result and Option Types:
use std::fs::File;
use std::io::{self, Read};
// Result type for operations that can fail
fn read_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?; // ? operator propagates errors
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
// Custom error types
#[derive(Debug)]
enum AppError {
Io(io::Error),
Parse(std::num::ParseIntError),
NotFound(String),
Validation(String),
}
impl From<io::Error> for AppError {
fn from(error: io::Error) -> Self {
AppError::Io(error)
}
}
// Using custom error type
fn read_number_from_file(path: &str) -> Result<i32, AppError> {
let contents = read_file(path)?; // Auto-converts io::Error
let number = contents.trim().parse()
.map_err(AppError::Parse)?; // Explicitly convert ParseIntError
Ok(number)
}
// Option for nullable values
fn find_user(id: &str) -> Option<User> {
users.iter().find(|u| u.id == id).cloned()
}
// Combining Option and Result
fn get_user_age(id: &str) -> Result<u32, AppError> {
find_user(id)
.ok_or_else(|| AppError::NotFound(id.to_string()))
.map(|user| user.age)
}
Go Error Handling
Explicit Error Returns:
// Basic error handling
func getUser(id string) (*User, error) {
user, err := db.QueryUser(id)
if err != nil {
return nil, fmt.Errorf("failed to query user: %w", err)
}
if user == nil {
return nil, errors.New("user not found")
}
return user, nil
}
// Custom error types
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation failed for %s: %s", e.Field, e.Message)
}
// Sentinel errors for comparison
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
ErrInvalidInput = errors.New("invalid input")
)
// Error checking
user, err := getUser("123")
if err != nil {
if errors.Is(err, ErrNotFound) {
// Handle not found
} else {
// Handle other errors
}
}
// Error wrapping and unwrapping
func processUser(id string) error {
user, err := getUser(id)
if err != nil {
return fmt.Errorf("process user failed: %w", err)
}
// Process user
return nil
}
// Unwrap errors
err := processUser("123")
if err != nil {
var valErr *ValidationError
if errors.As(err, &valErr) {
fmt.Printf("Validation error: %s\n", valErr.Field)
}
}
Universal Patterns
Pattern 1: Circuit Breaker
Prevent cascading failures in distributed systems.
from enum import Enum
from datetime import datetime, timedelta
from typing import Callable, TypeVar
T = TypeVar('T')
class CircuitState(Enum):
CLOSED = "closed" # Normal operation
OPEN = "open" # Failing, reject requests
---
*Content truncated.*
More by wshobson
View all skills by wshobson →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
pdf-to-markdown
aliceisjustplaying
Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.
Related MCP Servers
Browse all serversClaude Historian is a free AI search engine offering advanced search, file context, and solution discovery in Claude Cod
Claude Historian: AI-powered search for Claude Code conversations—find files, errors, context, and sessions via JSONL pa
OpenRouter offers seamless access to diverse AI models for multimodal vision and language, with smart model selection an
Securely query your MySQL host with read-only access, robust validation, and natural language search. Easily join MySQL
Boost productivity with Task Master: an AI-powered tool for project management and agile development workflows, integrat
Empower your CLI agents with NotebookLM—connect AI tools for citation-backed answers from your docs, grounded in your ow
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.