Go's error handling is verbose but explicit. The cost is real; the benefit is also real: every error is handled where it's returned. You cannot accidentally ignore an error without making it look deliberate.

The pattern everyone reaches for: `errors.Is` for sentinels, `errors.As` for type assertions, `fmt.Errorf("... %w", err)` for wrapping. The wrapped error chain is inspectable without depending on string matching.

The missing piece: no stack traces by default. For production debugging, either log context at the call site or use a library that captures them. pkg/errors is the historical choice; the stdlib `errors` package now covers most use cases.

See: [[debugging-as-search]], [[@dave/on-abstraction]]