1// Package errors provides simple error handling primitives. 2// 3// The traditional error handling idiom in Go is roughly akin to 4// 5// if err != nil { 6// return err 7// } 8// 9// which when applied recursively up the call stack results in error reports 10// without context or debugging information. The errors package allows 11// programmers to add context to the failure path in their code in a way 12// that does not destroy the original value of the error. 13// 14// Adding context to an error 15// 16// The errors.Wrap function returns a new error that adds context to the 17// original error by recording a stack trace at the point Wrap is called, 18// together with the supplied message. For example 19// 20// _, err := ioutil.ReadAll(r) 21// if err != nil { 22// return errors.Wrap(err, "read failed") 23// } 24// 25// If additional control is required, the errors.WithStack and 26// errors.WithMessage functions destructure errors.Wrap into its component 27// operations: annotating an error with a stack trace and with a message, 28// respectively. 29// 30// Retrieving the cause of an error 31// 32// Using errors.Wrap constructs a stack of errors, adding context to the 33// preceding error. Depending on the nature of the error it may be necessary 34// to reverse the operation of errors.Wrap to retrieve the original error 35// for inspection. Any error value which implements this interface 36// 37// type causer interface { 38// Cause() error 39// } 40// 41// can be inspected by errors.Cause. errors.Cause will recursively retrieve 42// the topmost error that does not implement causer, which is assumed to be 43// the original cause. For example: 44// 45// switch err := errors.Cause(err).(type) { 46// case *MyError: 47// // handle specifically 48// default: 49// // unknown error 50// } 51// 52// Although the causer interface is not exported by this package, it is 53// considered a part of its stable public interface. 54// 55// Formatted printing of errors 56// 57// All error values returned from this package implement fmt.Formatter and can 58// be formatted by the fmt package. The following verbs are supported: 59// 60// %s print the error. If the error has a Cause it will be 61// printed recursively. 62// %v see %s 63// %+v extended format. Each Frame of the error's StackTrace will 64// be printed in detail. 65// 66// Retrieving the stack trace of an error or wrapper 67// 68// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are 69// invoked. This information can be retrieved with the following interface: 70// 71// type stackTracer interface { 72// StackTrace() errors.StackTrace 73// } 74// 75// The returned errors.StackTrace type is defined as 76// 77// type StackTrace []Frame 78// 79// The Frame type represents a call site in the stack trace. Frame supports 80// the fmt.Formatter interface that can be used for printing information about 81// the stack trace of this error. For example: 82// 83// if err, ok := err.(stackTracer); ok { 84// for _, f := range err.StackTrace() { 85// fmt.Printf("%+s:%d\n", f, f) 86// } 87// } 88// 89// Although the stackTracer interface is not exported by this package, it is 90// considered a part of its stable public interface. 91// 92// See the documentation for Frame.Format for more details. 93package errors 94 95import ( 96 "fmt" 97 "io" 98) 99 100// New returns an error with the supplied message. 101// New also records the stack trace at the point it was called. 102func New(message string) error { 103 return &fundamental{ 104 msg: message, 105 stack: callers(), 106 } 107} 108 109// Errorf formats according to a format specifier and returns the string 110// as a value that satisfies error. 111// Errorf also records the stack trace at the point it was called. 112func Errorf(format string, args ...interface{}) error { 113 return &fundamental{ 114 msg: fmt.Sprintf(format, args...), 115 stack: callers(), 116 } 117} 118 119// fundamental is an error that has a message and a stack, but no caller. 120type fundamental struct { 121 msg string 122 *stack 123} 124 125func (f *fundamental) Error() string { return f.msg } 126 127func (f *fundamental) Format(s fmt.State, verb rune) { 128 switch verb { 129 case 'v': 130 if s.Flag('+') { 131 io.WriteString(s, f.msg) 132 f.stack.Format(s, verb) 133 return 134 } 135 fallthrough 136 case 's': 137 io.WriteString(s, f.msg) 138 case 'q': 139 fmt.Fprintf(s, "%q", f.msg) 140 } 141} 142 143// WithStack annotates err with a stack trace at the point WithStack was called. 144// If err is nil, WithStack returns nil. 145func WithStack(err error) error { 146 if err == nil { 147 return nil 148 } 149 return &withStack{ 150 err, 151 callers(), 152 } 153} 154 155type withStack struct { 156 error 157 *stack 158} 159 160func (w *withStack) Cause() error { return w.error } 161 162// Unwrap provides compatibility for Go 1.13 error chains. 163func (w *withStack) Unwrap() error { return w.error } 164 165func (w *withStack) Format(s fmt.State, verb rune) { 166 switch verb { 167 case 'v': 168 if s.Flag('+') { 169 fmt.Fprintf(s, "%+v", w.Cause()) 170 w.stack.Format(s, verb) 171 return 172 } 173 fallthrough 174 case 's': 175 io.WriteString(s, w.Error()) 176 case 'q': 177 fmt.Fprintf(s, "%q", w.Error()) 178 } 179} 180 181// Wrap returns an error annotating err with a stack trace 182// at the point Wrap is called, and the supplied message. 183// If err is nil, Wrap returns nil. 184func Wrap(err error, message string) error { 185 if err == nil { 186 return nil 187 } 188 err = &withMessage{ 189 cause: err, 190 msg: message, 191 } 192 return &withStack{ 193 err, 194 callers(), 195 } 196} 197 198// Wrapf returns an error annotating err with a stack trace 199// at the point Wrapf is called, and the format specifier. 200// If err is nil, Wrapf returns nil. 201func Wrapf(err error, format string, args ...interface{}) error { 202 if err == nil { 203 return nil 204 } 205 err = &withMessage{ 206 cause: err, 207 msg: fmt.Sprintf(format, args...), 208 } 209 return &withStack{ 210 err, 211 callers(), 212 } 213} 214 215// WithMessage annotates err with a new message. 216// If err is nil, WithMessage returns nil. 217func WithMessage(err error, message string) error { 218 if err == nil { 219 return nil 220 } 221 return &withMessage{ 222 cause: err, 223 msg: message, 224 } 225} 226 227// WithMessagef annotates err with the format specifier. 228// If err is nil, WithMessagef returns nil. 229func WithMessagef(err error, format string, args ...interface{}) error { 230 if err == nil { 231 return nil 232 } 233 return &withMessage{ 234 cause: err, 235 msg: fmt.Sprintf(format, args...), 236 } 237} 238 239type withMessage struct { 240 cause error 241 msg string 242} 243 244func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } 245func (w *withMessage) Cause() error { return w.cause } 246 247// Unwrap provides compatibility for Go 1.13 error chains. 248func (w *withMessage) Unwrap() error { return w.cause } 249 250func (w *withMessage) Format(s fmt.State, verb rune) { 251 switch verb { 252 case 'v': 253 if s.Flag('+') { 254 fmt.Fprintf(s, "%+v\n", w.Cause()) 255 io.WriteString(s, w.msg) 256 return 257 } 258 fallthrough 259 case 's', 'q': 260 io.WriteString(s, w.Error()) 261 } 262} 263 264// Cause returns the underlying cause of the error, if possible. 265// An error value has a cause if it implements the following 266// interface: 267// 268// type causer interface { 269// Cause() error 270// } 271// 272// If the error does not implement Cause, the original error will 273// be returned. If the error is nil, nil will be returned without further 274// investigation. 275func Cause(err error) error { 276 type causer interface { 277 Cause() error 278 } 279 280 for err != nil { 281 cause, ok := err.(causer) 282 if !ok { 283 break 284 } 285 err = cause.Cause() 286 } 287 return err 288} 289