| name | error-handling-patterns |
| description | Error handling strategy selection, recoverability analysis, and signaling techniques. Use when choosing between exceptions, result types, error codes, or other error handling approaches, designing error-handling APIs, wrapping third-party library errors, or evaluating whether errors should be explicit or implicit. |
Error Handling Patterns
Error Strategy Decision Table
| Situation | Strategy | Why |
|---|
| Invalid user input | Validate and return descriptive error | User can fix it; fail fast at boundary |
| Programming error (bug) | Crash / unchecked exception | Don't mask bugs; fix them |
| External system failure | Retry with backoff or circuit-break | Transient failures resolve; permanent ones need escalation |
| Expected business case (not found) | Return empty/Optional/Result | Not an error โ it's a valid outcome |
| Security violation | Log, deny, alert | Don't reveal details to caller |
| Resource exhaustion (OOM, disk) | Fail fast with clear message | Can't recover; make the failure diagnosable |
Recoverability Framework
Can the caller realistically recover?
โโโ Yes โ Use explicit signaling (Result type, checked exception)
โ โโโ Expected failure (not found, validation) โ Return type encodes the failure
โ โโโ Transient failure (timeout, rate limit) โ Retry with backoff
โโโ No โ Let it propagate (unchecked exception, panic)
โ โโโ Bug โ Crash and fix the code
โ โโโ Infrastructure failure โ Propagate to top-level handler
โโโ Caller determines โ Provide both options (Result + throw helper)
Signaling Comparison Table
| Technique | Explicit? | Composable? | Performance | Best For |
|---|
| Checked exceptions | Yes (compiler-enforced) | No | Moderate | Public APIs, Java |
| Unchecked exceptions | No (caller may miss) | No | Moderate | Bugs, unrecoverable |
| Result/Either types | Yes (type-enforced) | Yes (map/flatMap) | Low overhead | Functional style, Rust/Kotlin |
| Optional/Nullable | Partial | Partial | Low overhead | "Not found" cases only |
| Error codes | No (easy to ignore) | No | Minimal | Low-level, C interop, hot paths |
Error-Hiding Antipatterns
| Antipattern | Symptom | Severity | Fix |
|---|
| Empty catch block | catch (e) {} โ error vanishes | Critical | Handle, log, or propagate |
| Swallow and return null | catch โ return null hides root cause | Critical | Distinguish "not found" from "system error" |
| Log and continue | Error logged but execution continues in broken state | Warning | Decide: recover meaningfully or propagate |
| Generic catch-all | catch (Exception e) masks different failure modes | Warning | Catch specific exceptions; let unexpected ones propagate |
| Error as magic value | Return -1 or "" to signal failure | Warning | Use typed error channels (Result, Optional, exceptions) |
| Exception wrapping without context | throw new RuntimeException(e) | Note | Add domain context: throw new PaymentFailedException("charge declined", e) |
Strategy Selection Flowchart
What kind of code are you writing?
โโโ Public API / library
โ โโโ Caller must handle โ Checked exception or Result type
โ โโโ Caller can't handle โ Unchecked exception (document it)
โโโ Internal service code
โ โโโ Expected failure โ Result type
โ โโโ Bug / unexpected โ Let it propagate
โโโ Hot path (measured)
โ โโโ Error codes or Result types (avoid exception overhead)
โโโ Script / CLI
โโโ Crash with clear message (fail fast)
Checklist
Before shipping error handling code: