---
name: error-handling
description: >-
  Designs and implements robust error handling that fails gracefully, preserves context,
  and aids debugging. Use when adding error handling to code, reviewing error patterns,
  or user asks to "make this more robust" or "add error handling".
  NOT for debugging existing bugs or writing tests.
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
---

## Identity & Scope

**Executor:** either
**Model tier:** sonnet
**Scope:** Source code files requiring error handling improvements
**Off-limits:** Changing business logic, modifying database schemas, deploying
**Hard rules:** No credentials in output. No deleting files. No spending money. Report via structured output.

## Essential Principles

1. **Fail fast, fail loud** — Detect errors early and surface them with full context. Guards against: silent failures that corrupt data downstream.
2. **Catch specific, never bare** — Handle named exception types, never bare `except:`. Guards against: swallowing real bugs inside generic handlers.
3. **Preserve the chain** — Include original exception when re-raising (`from e`). Guards against: losing root cause in error transformation layers.
4. **Separate user from developer errors** — Users see actionable messages, developers see stack traces. Guards against: leaking internals to users or hiding details from developers.

## When to Use
- Adding error handling to code calling external systems, parsing input, or doing I/O
- Reviewing existing code for missing or weak error handling
- User asks to "make this robust" or "add error handling"
- Implementing retry logic, circuit breakers, or fallback patterns

## When NOT to Use
- Diagnosing an existing bug — use bug-debugging skill
- Writing tests for error paths — use test-writing skill
- Designing API error responses — use api-design skill
- Performance issues — use a profiling skill

## Rationalizations to Reject

| Shortcut | Why it's wrong |
|----------|----------------|
| "except Exception covers everything" | Hides real bugs like TypeError and AttributeError |
| "Error handling on main path only" | Errors cluster in edge paths — that's where handling matters |
| "Logging is enough" | Logging without handling means caller gets unhandled exception |
| "Retry will fix transient errors" | Retry without backoff hammers failing services |
| "The caller will handle it" | Every boundary must handle its own errors |

## Workflow

### Phase 1: Audit
**Entry:** Target codebase or files accessible
**Actions:**
1. Grep for bare except clauses, empty catch blocks, `pass` in handlers
2. Identify all external calls: HTTP, database, file I/O, subprocess
3. Check each external call for proper error handling
4. List unhandled failure points with file and line references
**Exit:** Inventory of error handling gaps with severity ratings

### Phase 2: Design
**Entry:** Gap inventory complete
**Actions:**
1. Determine strategy per gap: retry, fallback, raise, log-and-continue
2. Define specific exception types to catch at each point
3. Plan logging context: inputs, state, timing
4. Separate user-facing vs developer-facing messages
**Exit:** Error handling plan with strategy per gap

### Phase 3: Implement
**Entry:** Plan complete
**Actions:**
1. Add specific exception handlers at each identified gap
2. Include original exception in all re-raises
3. Add structured logging with context at each handler
4. Implement retry with exponential backoff where appropriate
**Exit:** All identified gaps addressed

### Phase 4: Verify
**Entry:** Implementation complete
**Actions:**
1. Grep for bare except clauses — confirm none remain
2. Verify every external call has error handling
3. Verify logging includes context (inputs, state) at each handler
4. Confirm output matches required JSON format
**Exit:** All checks pass — report results

## Output Format

```json
{
  "skill": "error-handling",
  "status": "completed",
  "worker": "worker-id",
  "summary": "Added error handling to 8 unprotected calls across 3 files, replaced 2 bare excepts",
  "findings": [
    {"item": "api_client.py:34 — ConnectionError+Timeout with 3x backoff", "severity": "high", "detail": "HTTP POST had no handling. Added retry (1s,2s,4s), fallback to queue on final failure"},
    {"item": "parser.py:12 — Replaced bare except with ValueError+KeyError", "severity": "medium", "detail": "Bare except hid TypeError bugs. Now catches ValueError for bad JSON, KeyError for missing fields"}
  ],
  "errors": [],
  "elapsed_seconds": 28.5
}
```

**Bad example:** `{"summary": "Added try/except blocks", "findings": [{"item": "Added error handling"}]}` — no specifics on exceptions caught, no file refs, "wrapped in try/except" IS the anti-pattern.

## Escalation Triggers

STOP and report to boss when:
- Error handling requires changing the public API contract
- Errors indicate data corruption or loss
- No logging infrastructure exists and adding one is out of scope
- Retry logic requires external configuration decisions
- Credentials found in error messages or logs

## Success Criteria

- [ ] No bare except clauses in modified code
- [ ] Every external call has specific error handling
- [ ] All re-raised exceptions preserve original cause
- [ ] Logging includes context at every handler
- [ ] User-facing and developer-facing errors separated
- [ ] Output matches JSON format above
- [ ] No unresolved escalation triggers
