# Error Handling Patterns

## Overview

Error handling patterns provide structured approaches to detecting, reporting, and recovering from failures. Good error handling makes systems robust, debuggable, and predictable. Poor error handling hides bugs, corrupts state, and produces cascading failures.

## Pattern Comparison

| Pattern | Purpose | Mechanism | Key Benefit |
|---|---|---|---|
| **Guard Clause** | Validate inputs at entry, bail early | Early return / raise | Flat, readable control flow |
| **Result Type** | Encode success-or-error in return value | `Result<T, E>` / Either | Compiler-enforced error handling |
| **Fail Fast** | Detect errors immediately at boundaries | Validate + abort on first error | Prevents silent corruption |
| **Exception Hierarchy** | Organize exceptions in a meaningful tree | Class inheritance | Granular catch + categorization |

## When to Use Which

- **Validating function arguments at the top?** Use **Guard Clause** to reject bad input early.
- **Returning errors without exceptions?** Use **Result Type** for explicit success/failure.
- **Want to crash immediately on invalid state?** Use **Fail Fast** to prevent downstream corruption.
- **Need categorised, catchable errors?** Use **Exception Hierarchy** for domain-specific error trees.

## Relationships Between Patterns

- **Guard Clause** is often the first check inside a function; it may raise exceptions from an **Exception Hierarchy** or return a **Result Type**.
- **Fail Fast** philosophy motivates **Guard Clauses** — both prefer early detection over late recovery.
- **Result Type** and **Exception Hierarchy** are alternative error-propagation mechanisms: Result is explicit in the type system; exceptions use control flow.
- Languages like Go and Rust strongly favour **Result Type**; Java and Python traditionally use **Exception Hierarchy**.

## Design Guidelines

1. **Be explicit** — callers should not be surprised by errors.
2. **Fail close to the source** — detect problems where they originate.
3. **Provide context** — error messages should include what went wrong, why, and what to do.
4. **Don't swallow errors** — empty `except:` / `catch` blocks hide bugs.
5. **Match error granularity to recovery needs** — don't over-categorise if callers won't distinguish.
