error-handling-patterns
Implement robust error handling patterns
Applications often fail unexpectedly due to poor error handling. This skill provides battle-tested patterns for exceptions, Result types, circuit breakers, and graceful degradation across Python, TypeScript, Rust, and Go.
Download the skill ZIP
Upload in Claude
Go to Settings → Capabilities → Skills → Upload skill
Toggle on and start using
Test it
Using "error-handling-patterns". Add error handling to a function that reads a file and parses JSON content.
Expected outcome:
Here is a pattern for robust file handling with proper error hierarchy:
**Python Example:**
```python
class FileReadError(ApplicationError):
"""Raised when file read operations fail."""
pass
class ParseError(ApplicationError):
"""Raised when JSON parsing fails."""
pass
def read_json_file(path: str) -> dict:
try:
with open(path, 'r') as f:
content = f.read()
return json.loads(content)
except FileNotFoundError as e:
raise FileReadError(f"File not found: {path}", details={"path": path}) from e
except json.JSONDecodeError as e:
raise ParseError(f"Invalid JSON in file: {path}", details={"path": path, "error": str(e)}) from e
```
**Key practices:**
- Use specific exception types for different error scenarios
- Include contextual information in exceptions
- Chain exceptions to preserve original stack trace
- Use context managers for automatic resource cleanup
Using "error-handling-patterns". How should I handle errors in an async function that calls multiple services in parallel?
Expected outcome:
For parallel service calls, consider these strategies:
**Option 1: Aggregate Errors**
Collect all errors and report them together rather than failing on the first error.
```typescript
async function fetchUserData(userId: string): Promise<UserData> {
const errors: Error[] = [];
let user: User | null = null;
let orders: Order[] = [];
try { user = await userService.getUser(userId); }
catch (e) { errors.push(e); }
try { orders = await orderService.getOrders(userId); }
catch (e) { errors.push(e); }
if (errors.length > 0) {
throw new AggregateError(errors, `${errors.length} operations failed`);
}
return { user, orders };
}
```
**Option 2: Result Types**
Use explicit success/failure types for each operation.
```typescript
async function fetchUserData(userId: string): Promise<Result<UserData>> {
const [userResult, ordersResult] = await Promise.all([
safePromise(userService.getUser(userId)),
safePromise(orderService.getOrders(userId))
]);
if (!userResult.ok) return Err(userResult.error);
if (!ordersResult.ok) return Err(ordersResult.error);
return Ok({ user: userResult.value, orders: ordersResult.value });
}
```
Using "error-handling-patterns". What are the worst error handling anti-patterns to avoid?
Expected outcome:
Here are the most dangerous anti-patterns and their fixes:
**Anti-Pattern 1: Empty Catch Blocks**
```python
try:
do_something()
except:
pass # Silent failure - bugs hide forever
```
**Fix:** Always log or re-raise exceptions.
**Anti-Pattern 2: Catching Too Broadly**
```python
try:
do_something()
except Exception:
# Hides bugs including typos and logic errors
pass
```
**Fix:** Catch specific exception types only.
**Anti-Pattern 3: Swallowing After Logging**
```python
try:
do_something()
except Exception as e:
logger.error(e)
# Error logged but not handled - caller doesn't know it failed
```
**Fix:** Re-raise or return error result.
**Anti-Pattern 4: Overly Generic Errors**
```python
raise Exception("Error occurred") # No context, no code, useless for debugging
```
**Fix:** Include what happened, what was being processed, and error codes.
Security Audit
SafeAll static findings are false positives. The skill is legitimate educational documentation about error handling patterns across Python, TypeScript, Rust, and Go. Static scanner misidentified 'error' keywords as cryptographic issues and Markdown code fences as shell backticks. No actual network calls, command execution, or malicious patterns exist in the skill content.
Quality Score
What You Can Build
Build production-grade API error handling
Design error handling for a new REST API that returns consistent error responses with proper HTTP status codes, error codes, and helpful messages for API consumers.
Add resilience to distributed systems
Implement circuit breaker and retry patterns to prevent cascading failures when external services become unavailable, ensuring the system degrades gracefully.
Improve code review feedback on error handling
Provide specific, actionable feedback on error handling in pull requests, identifying anti-patterns like empty catch blocks or overly broad exception handling.
Try These Prompts
I need error handling for a {language} function that calls an external API. The function should retry on network failures with exponential backoff, include proper error types, and provide clear error messages for debugging.Design a custom exception hierarchy for a {application_type} application. Include base exception class, specific error types for validation, not found, and external service failures. Each exception should include error code, timestamp, and relevant context.Implement a circuit breaker pattern for a service that makes calls to an unreliable third-party API. Include configuration for failure threshold, timeout duration, and half-open state for recovery testing.
Create a validation system that collects all validation errors rather than failing on the first one. Show how to aggregate errors from multiple fields and return them as a structured response.
Best Practices
- Create specific exception types with contextual information including error codes, timestamps, and relevant metadata for debugging
- Use Result types or explicit error returns for expected failures to make error handling forced and visible at compile time where possible
- Implement circuit breakers for external dependencies to prevent cascading failures and allow graceful degradation
- Log errors with appropriate severity - error-level for actual problems, warning for expected failures, never for normal flow
Avoid
- Empty catch blocks that silently swallow errors, hiding bugs and making debugging impossible
- Overly broad exception handlers like `except Exception` that mask programming errors alongside expected failures
- Logging exceptions without re-raising them, creating duplicate log entries and confusing control flow
- Returning generic error codes instead of typed exceptions, making error handling verbose and error-prone