# Designing Errors — Go (Golang)

Source: https://www.skillbyai.com/en/go/e-design

> Messages and types callers can use.

## Sentinels, types and handling once

Choose how callers will use an error: a **sentinel** (`var ErrNotFound = errors.New(...)`) for conditions they check, a **custom type** when they need details (a field name, a retry-after duration), or a plain wrapped error when they only log it. Error strings are lowercase without trailing punctuation, because they are combined. Handle each error **once**: either return it (with context) or log and handle it, but not both, to avoid duplicate logs.

## Error design choices

Pick based on what the caller needs.

```text
caller needs to...                         use
check a specific condition                  sentinel: var ErrNotFound = errors.New("not found")
read details (field, code, retry time)      custom type implementing Error()
just report it                              fmt.Errorf("load config: %w", err)
stop the program on an impossible state     panic (programmer error only)
```

## Log at the top, wrap below

Lower layers wrap and return; the outermost handler (request, job) logs once with full context.

**Quiz:** Why avoid both logging and returning the same error?

- [ ] Returning errors is forbidden
- [x] It produces duplicate log entries as the error moves up
- [ ] Logs cannot contain errors
- [ ] It changes the error type

*Answer:* It produces duplicate log entries as the error moves up. Handle an error once.
