errors

Guided tour · Errors & Logging · pkg.go.dev →

Error inspection, wrapping, and sentinel creation. The counterpart to fmt.Errorf("%w", ...).

Build, wrap, and inspect errors. Pair with fmt.Errorf %w to add context while keeping the underlying error inspectable.

Sentinel error
var ErrNoUser = errors.New("no user")
Wrap with context
return fmt.Errorf("load %s: %w", id, err)
Check kind
if errors.Is(err, ErrNoUser) { ... }
Extract typed error
var pe *fs.PathError
if errors.As(err, &pe) { use(pe.Path) }
Combine multiple
return errors.Join(e1, e2, e3)

Creating errors

errors.New — plain sentinel

var ErrNotFound = errors.New("not found")

if _, err := lookup(k); errors.Is(err, ErrNotFound) {
    // handle
}

fmt.Errorf — formatted and wrapping

Use %w to wrap. %v formats without wrapping. You can wrap multiple errors with several %w verbs (1.20+).

err := fmt.Errorf("open %s: %w", path, os.ErrNotExist)
fmt.Println(err)

// Multiple wrapping (Go 1.20+)
err = fmt.Errorf("%w; %w", io.EOF, errors.New("extra"))

errors.Join — combine independent errors

Useful when validating many fields or fanning out to several goroutines.

err := errors.Join(
    errors.New("name required"),
    errors.New("age invalid"),
)
fmt.Println(err)

Inspecting errors

errors.Is — sentinel comparison through wrappers

Use Is instead of == when checking for known sentinel errors — works even if they were wrapped with %w.

if errors.Is(err, os.ErrNotExist) {
    return newFile()
}

errors.As — extract a specific error type

As assigns into its target if any error in the chain matches that type.

var pathErr *os.PathError
if errors.As(err, &pathErr) {
    fmt.Println("path was", pathErr.Path)
}

errors.Unwrap — one layer off

Usually you want Is/As instead. Unwrap is for custom error walkers.

Custom error types

Implement Error() and optionally Unwrap()

type HTTPError struct {
    Code int
    Msg  string
    Err  error
}
func (e *HTTPError) Error() string { return fmt.Sprintf("%d: %s", e.Code, e.Msg) }
func (e *HTTPError) Unwrap() error { return e.Err }