Use when designing error-handling strategy for a feature — error classification, throw-vs-return conventions, retry/circuit-breaker/fallback decisions, and error-to-user-message mapping. Triggers on "error handling", "retry strategy", "circuit breaker", "error propagation", "错误处理", "重试策略", "熔断", "降级" — also when user says "这个错误该怎么处理" / "要不要重试". Not for diagnosing a specific bug (use debugging); system-level resilience architecture (use architecture).
Scanned 9/4/2026
Install to Claude Code
npx -y skills add int2t05/engineering-skills --skill error-handling --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Error Handling?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/int2t05-error-handling)More formats (shields.io, HTML) on the badges page.
---
name: error-handling
description: Use when designing error-handling strategy for a feature — error classification, throw-vs-return conventions, retry/circuit-breaker/fallback decisions, and error-to-user-message mapping. Triggers on "error handling", "retry strategy", "circuit breaker", "error propagation", "错误处理", "重试策略", "熔断", "降级" — also when user says "这个错误该怎么处理" / "要不要重试". Not for diagnosing a specific bug (use debugging); system-level resilience architecture (use architecture).
---
## When to use
- Designing how errors propagate across layers for a new feature or service boundary
- Choosing retry, circuit-breaker, or fallback strategy for calls to external systems
- Establishing throw-vs-return conventions for a module or codebase
- Mapping internal errors to user-facing messages at an edge boundary
**Not for:** diagnosing a specific bug or test failure (use `debugging`); system-level resilience architecture — cross-service error strategy, overall failure posture (use `architecture`, specifically `architecture/references/error-resilience.md`); API error response envelope shape (use `api-design`); production logging/metrics instrumentation (use `observability`).
## Steps
For system-level resilience architecture (cross-service error propagation, failure posture design), read [architecture's error-resilience reference](${CLAUDE_PLUGIN_ROOT}/skills/03-design/architecture/references/error-resilience.md) first. This skill is the implementation-level companion — the decisions you make at the keyboard when writing the error-handling code.
### 1. Classify errors
Every error falls into one of four categories, and the category drives the strategy:
| Category | Examples | Strategy |
|---|---|---|
| **Transient** | network timeout, 503, connection reset | retry with backoff (step 3) |
| **Permanent** | 404, 400, logic failure | fail fast, no retry |
| **Validation** | bad input, schema mismatch | return 422-style result to caller |
| **Auth** | expired token, insufficient scope | return 401/403, prompt re-auth |
If you can't classify an error, default to permanent — retrying an unclassified error masks real bugs.
### 2. Choose throw-vs-return convention
Pick one convention per layer and enforce it (architecture ref §1 has the full rationale):
- **Throw (exceptions)** for invariant violations and infrastructure failures — "this should never happen, the operation cannot continue." Catch at boundaries, not at every call.
- **Return (Result/error values)** for expected, recoverable failures the caller must branch on — not-found, conflict, validation. A 404 is a result, not an exception.
Follow the language ecosystem's dominant convention: Rust/Go return error values; Python/Java/JS throw. Fighting the ecosystem creates inconsistent code.
### 3. Design retry strategy (transient errors only)
Retry only transient errors. Retrying permanent errors wastes resources and can amplify failures. See [references/retry-patterns.md](references/retry-patterns.md) for formulas and code.
- **Exponential backoff + jitter:** base × 2^n, capped, with jitter to prevent retry stampedes. Full jitter (random between 0 and the capped value) is the safe default.
- **Max attempts:** 3 covers most transient blips. More than 5 rarely helps and delays failure.
- **Idempotency:** retry only idempotent operations (GET, PUT, DELETE with stable IDs). For POST, require an idempotency key so a retry after an ambiguous timeout doesn't double-charge or double-create.
- **Timeout on every call.** A call without a timeout can hang forever and hold resources.
### 4. Add circuit breaker when retry is not enough
Retry handles isolated transient failures. A circuit breaker protects a struggling downstream from retry storms during a sustained outage.
- **States:** closed (normal) → open (fail fast, no calls) → half-open (probe one request to test recovery).
- **Open threshold:** N consecutive failures or a failure-rate threshold (e.g., 50% over a rolling window).
- **Cooldown:** fixed time or exponential reset. Half-open probes one request; success closes, failure re-opens.
- **Use when:** a downstream dependency has repeated sustained outages and retries would make things worse. Don't add a circuit breaker for a call that rarely fails.
### 5. Plan graceful degradation
When a dependency fails, decide what the user gets instead:
- **Critical path** (payment, auth, core data): fail the request — no degradation.
- **Non-critical path** (recommendations, search, analytics): catch the failure, serve a fallback (cached data, empty state, default) — the core page still renders.
- **Feature-flag kill switch:** for integration failures that recur, a flag to disable the feature path instantly beats debugging under load.
### 6. Map errors to user-facing messages (at the edge)
Maintain a single mapping from stable error codes to user-facing messages, at the edge boundary (architecture ref §3):
- **Stable error codes** (`PAYMENT_DECLINED`, `RATE_LIMITED`), not free text. The code is the cross-service contract.
- **Generic external, specific internal:** never expose SQL fragments, stack traces, or internal hostnames to users. Map to "Could not complete this action" + a correlation ID for support.
- **Actionable:** tell the user what to do ("Check your payment details and try again").
### 7. Log with structured context
Log every error with enough context to reproduce the diagnosis without re-running:
- Structured fields: error code, operation, correlation ID, request context.
- No secrets: redact tokens, passwords, PII before logging (see `debugging` skill's redaction discipline).
- Log at the boundary where the error is handled, not at every catch site — duplicated logs obscure the real failure path.
## Verify
- [ ] Every error in the new code is classified (transient / permanent / validation / auth) — strategy follows classification
- [ ] Throw-vs-return convention is consistent within each layer; no exceptions used for expected control flow
- [ ] Retry only fires on transient, idempotent operations; max attempts and backoff are set
- [ ] Circuit breaker (if used) has defined thresholds, cooldown, and half-open probe logic
- [ ] Non-critical dependency failures degrade gracefully (fallback/empty state), not cascade to a full page failure
- [ ] User-facing errors use stable codes + generic messages; no internal details leak
- [ ] Errors are logged with structured context and a correlation ID; no secrets in log output
- [ ] Tests cover: retry on transient, no-retry on permanent, circuit-breaker open/half-open/closed transitions, fallback path
## References
- [${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md](${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md) — discipline shared by every skill
- [${CLAUDE_PLUGIN_ROOT}/skills/03-design/architecture/references/error-resilience.md](${CLAUDE_PLUGIN_ROOT}/skills/03-design/architecture/references/error-resilience.md) — system-level resilience architecture (cross-layer error propagation, failure posture); this skill is its implementation-level companion
- [references/retry-patterns.md](references/retry-patterns.md) — backoff/jitter formulas, circuit breaker state machine, idempotency-key patterns, retry budgets (with code)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!