errors.New — plain sentinel
var ErrNotFound = errors.New("not found")
if _, err := lookup(k); errors.Is(err, ErrNotFound) {
// handle
}
errorsError 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.
var ErrNoUser = errors.New("no user")
return fmt.Errorf("load %s: %w", id, err)
if errors.Is(err, ErrNoUser) { ... }
var pe *fs.PathError
if errors.As(err, &pe) { use(pe.Path) }
return errors.Join(e1, e2, e3)
var ErrNotFound = errors.New("not found")
if _, err := lookup(k); errors.Is(err, ErrNotFound) {
// handle
}
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"))
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)
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()
}
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)
}
Usually you want Is/As instead. Unwrap is for custom error walkers.
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 }