go-error-handlinglisted
Install: claude install-skill muratmirgun/gophers
# Go Error Handling
Errors in Go are values. Treat them as part of the API: choose a strategy per failure mode, propagate with wrapping, inspect with `errors.Is`/`As`, and handle each error **exactly once**.
## Core Rules
1. **Errors are values, not exceptions.** Return them; do not panic across API boundaries.
2. **Handle each error exactly once.** *Either* log it *or* return it — never both.
3. **The caller decides what is exceptional.** Library code returns; binaries (or top-level handlers) decide whether to log, retry, or exit.
4. **Wrap only when you add real context.** A wrap that just repeats the function name is noise. Use `%w` to preserve identity; `%v` to deliberately hide an unstable type.
## Strategy Decision
Pick the simplest strategy that meets the caller's needs:
| Strategy | When to use | Example |
|---|---|---|
| **Opaque error** (default) | Caller only needs to know *something* failed | `errors.New("invalid input")` |
| **Sentinel error** | Caller needs to test for a specific named condition | `io.EOF`, `sql.ErrNoRows` |
| **Typed error** | Caller needs structured fields (path, code, retry-after) | `*os.PathError`, `*url.Error` |
| **Joined errors** | A single operation produced several independent failures | `errors.Join(errA, errB)` |
> Read [references/strategy-decision.md](references/strategy-decision.md) when the caller's needs are unclear or when migrating between strategies without breaking callers.
## Writing Errors
### Strings
- **Lowercas