Skills error-handling-patterns
📦

error-handling-patterns

Safe

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.

Supports: Claude Codex Code(CC)
🥉 72 Bronze
1

Download the skill ZIP

2

Upload in Claude

Go to Settings → Capabilities → Skills → Upload skill

3

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

Safe
v5 • 1/21/2026

All 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.

2
Files scanned
1,236
Lines analyzed
0
findings
5
Total audits
No security issues found
Audited by: claude View Audit History →

Quality Score

38
Architecture
100
Maintainability
87
Content
41
Community
100
Security
87
Spec Compliance

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

Basic error handling implementation
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.
Custom exception hierarchy design
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.
Circuit breaker integration
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.
Multi-error validation aggregation
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

Frequently Asked Questions

When should I use exceptions versus Result types?
Use exceptions for unexpected, exceptional conditions like network failures, file not found, or programming bugs. Use Result types for expected failures like validation errors, rate limiting, or business rule violations. Exceptions disrupt control flow while Result types make error handling explicit and forced.
How do I design a good error hierarchy?
Start with a base ApplicationError that captures common fields like timestamp, error code, and context. Create specific subclasses for each error domain: ValidationError, NotFoundError, ExternalServiceError, AuthenticationError. Avoid deep inheritance hierarchies - 2-3 levels is typically sufficient.
What is a circuit breaker and when should I use one?
A circuit breaker prevents cascading failures by stopping requests to a failing service. It has three states: closed (normal operation), open (requests fail fast), and half-open (testing recovery). Use it for any external service call where repeated failures could exhaust resources or affect user experience.
How should I handle errors in async code?
In async/await code, use try/catch around await statements. For Promise chains, always add .catch() handlers. Be careful with unhandled promise rejections - they can crash Node.js processes. Consider Result types for async operations to make failures explicit.
What information should I include in error messages?
Include what operation was attempted, what the input or resource was, why it failed, and what the user or developer can do about it. Avoid exposing sensitive data. Use structured formats with error codes for programmatic handling.
How do I test error handling effectively?
Test each error path explicitly using mocking to trigger specific failures. Verify that errors contain expected context and codes. Test retry logic by simulating transient failures. Ensure circuit breakers transition between states correctly under failure conditions.

Developer Details

File structure

📄 SKILL.md