README

errwrap

errwrap is a package for Go that formalizes the pattern of wrapping errors and checking if an error contains another error.

There is a common pattern in Go of taking a returned error value and then wrapping it (such as with fmt.Errorf) before returning it. The problem with this pattern is that you completely lose the original error structure.

Arguably the correct approach is that you should make a custom structure implementing the error interface, and have the original error as a field on that structure, such as this example. This is a good approach, but you have to know the entire chain of possible rewrapping that happens, when you might just care about one.

errwrap formalizes this pattern (it doesn't matter what approach you use above) by giving a single interface for wrapping errors, checking if a specific error is wrapped, and extracting that error.

Installation and Docs

Install using go get github.com/hashicorp/errwrap.

Full documentation is available at http://godoc.org/github.com/hashicorp/errwrap

Usage

Basic Usage

Below is a very basic example of its usage:

// A function that always returns an error, but wraps it, like a real
// function might.
func tryOpen() error {
	_, err := os.Open("/i/dont/exist")
	if err != nil {
		return errwrap.Wrapf("Doesn't exist: {{err}}", err)
	}

	return nil
}

func main() {
	err := tryOpen()

	// We can use the Contains helpers to check if an error contains
	// another error. It is safe to do this with a nil error, or with
	// an error that doesn't even use the errwrap package.
	if errwrap.Contains(err, "does not exist") {
		// Do something
	}
	if errwrap.ContainsType(err, new(os.PathError)) {
		// Do something
	}

	// Or we can use the associated `Get` functions to just extract
	// a specific error. This would return nil if that specific error doesn't
	// exist.
	perr := errwrap.GetType(err, new(os.PathError))
}
Custom Types

If you're already making custom types that properly wrap errors, then you can get all the functionality of errwraps.Contains and such by implementing the Wrapper interface with just one function. Example:

type AppError {
  Code ErrorCode
  Err  error
}

func (e *AppError) WrappedErrors() []error {
  return []error{e.Err}
}

Now this works:

err := &AppError{Err: fmt.Errorf("an error")}
if errwrap.ContainsType(err, fmt.Errorf("")) {
	// This will work!
}
Expand ▾ Collapse ▴

Documentation

Overview

    Package errwrap implements methods to formalize error wrapping in Go.

    All of the top-level functions that take an `error` are built to be able to take any error, not just wrapped errors. This allows you to use errwrap without having to type-check and type-cast everywhere.

    Index

    Constants

    This section is empty.

    Variables

    This section is empty.

    Functions

    func Contains

    func Contains(err error, msg string) bool

      Contains checks if the given error contains an error with the message msg. If err is not a wrapped error, this will always return false unless the error itself happens to match this msg.

      func ContainsType

      func ContainsType(err error, v interface{}) bool

        ContainsType checks if the given error contains an error with the same concrete type as v. If err is not a wrapped error, this will check the err itself.

        func Get

        func Get(err error, msg string) error

          Get is the same as GetAll but returns the deepest matching error.

          func GetAll

          func GetAll(err error, msg string) []error

            GetAll gets all the errors that might be wrapped in err with the given message. The order of the errors is such that the outermost matching error (the most recent wrap) is index zero, and so on.

            func GetAllType

            func GetAllType(err error, v interface{}) []error

              GetAllType gets all the errors that are the same type as v.

              The order of the return value is the same as described in GetAll.

              func GetType

              func GetType(err error, v interface{}) error

                GetType is the same as GetAllType but returns the deepest matching error.

                func Walk

                func Walk(err error, cb WalkFunc)

                  Walk walks all the wrapped errors in err and calls the callback. If err isn't a wrapped error, this will be called once for err. If err is a wrapped error, the callback will be called for both the wrapper that implements error as well as the wrapped error itself.

                  func Wrap

                  func Wrap(outer, inner error) error

                    Wrap defines that outer wraps inner, returning an error type that can be cleanly used with the other methods in this package, such as Contains, GetAll, etc.

                    This function won't modify the error message at all (the outer message will be used).

                    func Wrapf

                    func Wrapf(format string, err error) error

                      Wrapf wraps an error with a formatting message. This is similar to using `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap errors, you should replace it with this.

                      format is the format of the error message. The string '{{err}}' will be replaced with the original error message.

                      Deprecated: Use fmt.Errorf()

                      Types

                      type WalkFunc

                      type WalkFunc func(error)

                        WalkFunc is the callback called for Walk.

                        type Wrapper

                        type Wrapper interface {
                        	WrappedErrors() []error
                        }

                          Wrapper is an interface that can be implemented by custom types to have all the Contains, Get, etc. functions in errwrap work.

                          When Walk reaches a Wrapper, it will call the callback for every wrapped error in addition to the wrapper itself. Since all the top-level functions in errwrap use Walk, this means that all those functions work with your custom type.

                          Source Files