Working with Errors in Go 1.13
17 Oct 2019
Tags: errors, technical

Damien Neil and Jonathan Amsterdam

* Introduction

Go’s treatment of [[https://blog.golang.org/errors-are-values][errors as values]]
has served us well over the last decade. Although the standard library’s support
for errors has been minimal—just the `errors.New` and `fmt.Errorf` functions,
which produce errors that contain only a message—the built-in `error` interface
allows Go programmers to add whatever information they desire. All it requires
is a type that implements an `Error` method:


    type QueryError struct {
        Query string
        Err   error
    }

    func (e *QueryError) Error() string { return e.Query + ": " + e.Err.Error() }

Error types like this one are ubiquitous, and the information they store varies
widely, from timestamps to filenames to server addresses. Often, that
information includes another, lower-level error to provide additional context.

The pattern of one error containing another is so pervasive in Go code that,
after [[https://golang.org/issue/29934][extensive discussion]], Go 1.13 added
explicit support for it. This post describes the additions to the standard
library that provide that support: three new functions in the `errors` package,
and a new formatting verb for `fmt.Errorf`.

Before describing the changes in detail, let's review how errors are examined
and constructed in previous versions of the language.

* Errors before Go 1.13

** Examining errors

Go errors are values. Programs make decisions based on those values in a few
ways. The most common is to compare an error to `nil` to see if an operation
failed.

    if err != nil {
        // something went wrong
    }

Sometimes we compare an error to a known _sentinel_ value, to see if a specific error has occurred.

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

    if err == ErrNotFound {
        // something wasn't found
    }

An error value may be of any type which satisfies the language-defined `error`
interface. A program can use a type assertion or type switch to view an error
value as a more specific type.

    type NotFoundError struct {
        Name string
    }

    func (e *NotFoundError) Error() string { return e.Name + ": not found" }

    if e, ok := err.(*NotFoundError); ok {
        // e.Name wasn't found
    }


** Adding information

Frequently a function passes an error up the call stack while adding information
to it, like a brief description of what was happening when the error occurred. A
simple way to do this is to construct a new error that includes the text of the
previous one:

    if err != nil {
        return fmt.Errorf("decompress %v: %v", name, err)
    }

Creating a new error with `fmt.Errorf` discards everything from the original
error except the text. As we saw above with `QueryError`, we may sometimes want
to define a new error type that contains the underlying error, preserving it for
inspection by code. Here is `QueryError` again:


    type QueryError struct {
        Query string
        Err   error
    }

Programs can look inside a `*QueryError` value to make decisions based on the
underlying error. You'll sometimes see this referred to as "unwrapping" the
error.

    if e, ok := err.(*QueryError); ok && e.Err == ErrPermission {
        // query failed because of a permission problem
    }


The `os.PathError` type in the standard library is another example of one error which contains another.

* Errors in Go 1.13

** The Unwrap method

Go 1.13 introduces new features to the `errors` and `fmt` standard library
packages to simplify working with errors that contain other errors. The most
significant of these is a convention rather than a change: an error which
contains another may implement an `Unwrap` method returning the underlying
error. If `e1.Unwrap()` returns `e2`, then we say that `e1` _wraps_ `e2`, and
that you can _unwrap_ `e1` to get `e2`.

Following this convention, we can give the `QueryError` type above an `Unwrap`
method that returns its contained error:

    func (e *QueryError) Unwrap() error { return e.Err }

The result of unwrapping an error may itself have an `Unwrap` method; we call
the sequence of errors produced by repeated unwrapping the _error_chain_.

** Examining errors with Is and As

The Go 1.13 `errors` package includes two new functions for examining errors: `Is` and `As`. 

The `errors.Is` function compares an error to a value.

    // Similar to:
    //   if err == ErrNotFound { … }
    if errors.Is(err, ErrNotFound) {
        // something wasn't found
    }

The `As` function tests whether an error is a specific type.

    // Similar to:
    //   if e, ok := err.(*QueryError); ok { … }
    var e *QueryError
    if errors.As(err, &e) {
        // err is a *QueryError, and e is set to the error's value
    }

In the simplest case, the `errors.Is` function behaves like a comparison to a
sentinel error, and the `errors.As` function behaves like a type assertion. When
operating on wrapped errors, however, these functions consider all the errors in
a chain. Let's look again at the example from above of unwrapping a `QueryError`
to examine the underlying error:

    if e, ok := err.(*QueryError); ok && e.Err == ErrPermission {
        // query failed because of a permission problem
    }

Using the `errors.Is` function, we can write this as:

    if errors.Is(err, ErrPermission) {
        // err, or some error that it wraps, is a permission problem
    }


The `errors` package also includes a new `Unwrap` function which returns the
result of calling an error's `Unwrap` method, or `nil` when the error has no
`Unwrap` method. It is usually better to use `errors.Is` or `errors.As`,
however, since these functions will examine the entire chain in a single call.

** Wrapping errors with %w

As mentioned earlier, it is common to use the `fmt.Errorf` function to add additional information to an error.

    if err != nil {
        return fmt.Errorf("decompress %v: %v", name, err)
    }

In Go 1.13, the `fmt.Errorf` function supports a new `%w` verb. When this verb
is present, the error returned by `fmt.Errorf` will have an `Unwrap` method
returning the argument of `%w`, which must be an error. In all other ways, `%w`
is identical to `%v`.

    if err != nil {
        // Return an error which unwraps to err.
        return fmt.Errorf("decompress %v: %w", name, err)
    }

Wrapping an error with `%w` makes it available to `errors.Is` and `errors.As`:

    err := fmt.Errorf("access denied: %w", ErrPermission)
    ...
    if errors.Is(err, ErrPermission) ...


** Whether to Wrap

When adding additional context to an error, either with `fmt.Errorf` or by
implementing a custom type, you need to decide whether the new error should wrap
the original. There is no single answer to this question; it depends on the
context in which the new error is created. Wrap an error to expose it to
callers. Do not wrap an error when doing so would expose implementation details.

As one example, imagine a `Parse` function which reads a complex data structure
from an `io.Reader`. If an error occurs, we wish to report the line and column
number at which it occurred. If the error occurs while reading from the
`io.Reader`, we will want to wrap that error to allow inspection of the
underlying problem. Since the caller provided the `io.Reader` to the function,
it makes sense to expose the error produced by it.

In contrast, a function which makes several calls to a database probably should
not return an error which unwraps to the result of one of those calls. If the
database used by the function is an implementation detail, then exposing these
errors is a violation of abstraction. For example, if the `LookupUser` function
of your package `pkg` uses Go's `database/sql` package, then it may encounter a
`sql.ErrNoRows` error. If you return that error with
`fmt.Errorf("accessing`DB:`%v",`err)`
then a caller cannot look inside to find the `sql.ErrNoRows`. But if
the function instead returns `fmt.Errorf("accessing`DB:`%w",`err)`, then a
caller could reasonably write

    err := pkg.LookupUser(...)
    if errors.Is(err, sql.ErrNoRows) …

At that point, the function must always return `sql.ErrNoRows` if you don't want
to break your clients, even if you switch to a different database package. In
other words, wrapping an error makes that error part of your API. If you don't
want to commit to supporting that error as part of your API in the future, you
shouldn't wrap the error.

It’s important to remember that whether you wrap or not, the error text will be
the same. A _person_ trying to understand the error will have the same information
either way; the choice to wrap is about whether to give _programs_ additional
information so they can make more informed decisions, or to withhold that
information to preserve an abstraction layer.

* Customizing error tests with Is and As methods

The `errors.Is` function examines each error in a chain for a match with a
target value. By default, an error matches the target if the two are equal. In
addition, an error in the chain may declare that it matches a target by
implementing an `Is` _method_.

As an example, consider this error inspired by the
[[https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html][Upspin error package]]
which compares an error against a template, considering only fields which are
non-zero in the template:

    type Error struct {
        Path string
        User string
    }

    func (e *Error) Is(target error) bool {
        t, ok := target.(*Error)
        if !ok {
            return false
        }
        return (e.Path == t.Path || t.Path == "") &&
               (e.User == t.User || t.User == "")
    }

    if errors.Is(err, &Error{User: "someuser"}) {
        // err's User field is "someuser".
    }

The `errors.As` function similarly consults an `As` method when present.

* Errors and package APIs

A package which returns errors (and most do) should describe what properties of
those errors programmers may rely on. A well-designed package will also avoid
returning errors with properties that should not be relied upon.

The simplest specification is to say that operations either succeed or fail,
returning a nil or non-nil error value respectively. In many cases, no further
information is needed.

If we wish a function to return an identifiable error condition, such as "item
not found," we might return an error wrapping a sentinel.

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

    // FetchItem returns the named item.
    //
    // If no item with the name exists, FetchItem returns an error
    // wrapping ErrNotFound.
    func FetchItem(name string) (*Item, error) {
        if itemNotFound(name) {
            return nil, fmt.Errorf("%q: %w", name, ErrNotFound)
        }
        // ...
    }

There are other existing patterns for providing errors which can be semantically
examined by the caller, such as directly returning a sentinel value, a specific
type, or a value which can be examined with a predicate function.

In all cases, care should be taken not to expose internal details to the user.
As we touched on in "Whether to Wrap" above, when you return
an error from another package you should convert the error to a form that does
not expose the underlying error, unless you are willing to commit to returning
that specific error in the future.

    f, err := os.Open(filename)
    if err != nil {
        // The *os.PathError returned by os.Open is an internal detail.
        // To avoid exposing it to the caller, repackage it as a new
        // error with the same text. We use the %v formatting verb, since
        // %w would permit the caller to unwrap the original *os.PathError.
        return fmt.Errorf("%v", err)
    }

If a function is defined as returning an error wrapping some sentinel or type,
do not return the underlying error directly.

    var ErrPermission = errors.New("permission denied")

    // DoSomething returns an error wrapping ErrPermission if the user
    // does not have permission to do something.
    func DoSomething() error {
        if !userHasPermission() {
            // If we return ErrPermission directly, callers might come
            // to depend on the exact error value, writing code like this:
            //
            //     if err := pkg.DoSomething(); err == pkg.ErrPermission { … }
            //
            // This will cause problems if we want to add additional
            // context to the error in the future. To avoid this, we
            // return an error wrapping the sentinel so that users must
            // always unwrap it:
            //
            //     if err := pkg.DoSomething(); errors.Is(err, pkg.ErrPermission) { ... }
            return fmt.Errorf("%w", ErrPermission)
        }
        // ...
    }

* Conclusion

Although the changes we’ve discussed amount to just three functions and a
formatting verb, we hope they will go a long way toward improving how errors are
handled in Go programs. We expect that wrapping to provide additional context
will become commonplace, helping programs to make better decisions and helping
programmers to find bugs more quickly.

As Russ Cox said in his [[https://blog.golang.org/experiment][GopherCon 2019 keynote]],
on the path to Go 2 we experiment, simplify and ship. Now that we’ve
shipped these changes, we look forward to the experiments that will follow.
