Documentation ¶
Overview ¶
Package errz is sq's error package. It annotates errors with stack traces, and provides functionality for working with multiple errors, and error chains.
This package is the lovechild of Dave Cheney's pkg/errors and Uber's go.uber.org/multierr, and much of the code is borrowed from those packages.
Index ¶
- Variables
- func Append(left, right error) error
- func As[E error](err error) (E, bool)
- func Chain(err error) []error
- func Combine(errs ...error) error
- func Drain(errCh <-chan error) error
- func Err(err error, opts ...Opt) error
- func Errorf(format string, args ...any) error
- func Errors(err error) []error
- func Every(err, target error) bool
- func ExitCode(err error) (code int)
- func Has[E error](err error) bool
- func IsContextStop(ctx context.Context) bool
- func IsErrContext(err error) bool
- func New(message string, opts ...Opt) error
- func Return[T any](t T, err error) (T, error)
- func SprintTreeTypes(err error) string
- func UnwrapChain(err error) error
- func WithExitCode(err error, code int) error
- func Wrap(err error, message string) error
- func Wrapf(err error, format string, args ...any) error
- type ExitCoder
- type Frame
- type Frames
- type Opt
- type Skip
- type StackTrace
Constants ¶
This section is empty.
Variables ¶
var ErrNoMsg = errors.New("")
ErrNoMsg is a sentinel error indicating that a command has failed (and thus the program should exit with a non-zero code), but no error message should be printed. This is useful in the case where any error information may already have been printed as part of the command output.
var ErrStop = errors.New("explicit stop")
ErrStop is a sentinel error a la io.EOF used to indicate that an explicit stop condition has been reached. The stop condition is typically not an indication of a failure state, but rather a signal to stop processing. It is usually used in conjunction with context.CancelCauseFunc.
See: IsContextStop.
Functions ¶
func Append ¶
Append appends the given errors together. Either value may be nil. The value of the returned error's [error.Error] method is a semicolon-delimited list of the non-nil errors' messages. This is different from the behavior of stdlib errors.Join, which separates errors with newlines. But, we choose to use semicolons because it's more readable in logs and error messages.
This function is a specialization of Combine for the common case where there are only two errors.
err = multierr.Append(reader.Close(), writer.Close())
The following pattern may also be used to record failure of deferred operations without losing information about the original error.
func doSomething(..) (err error) { f := acquireResource() defer func() { err = multierr.Append(err, f.Close()) }()
Note that the variable MUST be a named return to append an error to it from the defer statement.
func As ¶ added in v0.47.0
As is a convenience wrapper around errors.As.
_, err := os.Open("non-existing") pathErr, ok := errz.As[*fs.PathError](err) require.True(t, ok) require.Equal(t, "non-existing", pathErr.Path)
If err is nil, As returns false. See also: errz.Has.
func Combine ¶
Combine combines the passed errors into a single error.
If zero arguments were passed or if all items are nil, a nil error is returned.
Combine(nil, nil) // == nil
If only a single error was passed, it is returned as-is.
Combine(err) // == err
Combine skips over nil arguments so this function may be used to combine together errors from operations that fail independently of each other.
multierr.Combine( reader.Close(), writer.Close(), pipe.Close(), )
If any of the passed errors is a multierr error, it will be flattened along with the other errors.
multierr.Combine(multierr.Combine(err1, err2), err3) // is the same as multierr.Combine(err1, err2, err3)
The returned error formats into a readable multi-line error message if formatted with %+v.
fmt.Sprintf("%+v", multierr.Combine(err1, err2))
func Drain ¶ added in v0.48.0
Drain reads all currently available non-nil errors from errCh. If errCh is nil, or there are no errors to read, Drain returns nil. If there's only a single error, Drain returns it. If there are multiple errors, Drain returns a multi-error created via errz.Append. Drain does not block; it does not wait for errCh to be closed. Thus, invoking Drain again on the same errCh may yield additional errors.
func Err ¶
Err annotates err with a stack trace at the point Err was called. It is equivalent to Wrap(err, ""). If err is nil, Err returns nil.
func Errorf ¶
Errorf works like fmt.Errorf, but it also records the stack trace at the point it was called. If the format string includes the %w verb, fmt.Errorf is first called to construct the error, and then the returned error is again wrapped to record the stack trace.
func Errors ¶
Errors returns a slice containing zero or more errors that the supplied error is composed of. If the error is nil, a nil slice is returned.
err := multierr.Append(r.Close(), w.Close()) errors := multierr.Errors(err)
If the error is not composed of other errors, the returned slice contains just the error that was passed in.
Callers of this function are free to modify the returned slice.
func Every ¶ added in v0.47.0
Every compares every error in the given err against the given target error using errors.Is, and returns true only if every comparison returned true.
func ExitCode ¶ added in v0.47.4
ExitCode returns the exit code of the first error in err's chain that implements ExitCoder, otherwise -1.
func Has ¶ added in v0.47.0
Has returns true if err, or an error in its error tree, matches error type E. An error is considered a match by the rules of errors.As:
f, err := os.Open("non-existing") if errz.Has[*fs.PathError](err) { // Do something }
If err is nil, Has returns false. See also: errz.As.
func IsContextStop ¶ added in v0.48.0
IsContextStop returns true if ctx's cause error is ErrStop.
func IsErrContext ¶ added in v0.48.0
IsErrContext returns true if err's chain contains context.Canceled or context.DeadlineExceeded.
func New ¶
New returns an error with the supplied message, recording the stack trace at the point it was called.
func Return ¶ added in v0.47.0
Return returns t with err wrapped via errz.Err. This is useful for the common case of returning a value and an error from a function.
written, err = errz.Return(io.Copy(w, r))
func SprintTreeTypes ¶ added in v0.47.0
SprintTreeTypes returns a string representation of err's type tree. A multi-error is represented as a slice of its children.
func UnwrapChain ¶ added in v0.47.0
UnwrapChain returns the underlying *root* cause of the error. That is to say, UnwrapChain returns the final non-nil error in the error chain. UnwrapChain returns nil if err is nil.
func WithExitCode ¶ added in v0.48.0
WithExitCode returns an error that implements ExitCoder, if err is non-nil. If err is nil, WithExitCode returns nil. If err already implements ExitCoder and its exit code is the same as code, WithExitCode returns err unchanged.
Types ¶
type ExitCoder ¶ added in v0.47.4
type ExitCoder interface { // ExitCode returns the exit code indicated by the error, or -1 if // the error does not indicate a particular exit code. ExitCode() int }
ExitCoder is an interface that an error type can implement to indicate that the program should exit with a specific status code. In particular, note that *exec.ExitError implements this interface.
type Frame ¶ added in v0.31.0
type Frame uintptr
Frame represents a program counter inside a stack frame. For historical reasons if Frame is interpreted as a uintptr its value represents the program counter + 1.
func (Frame) Format ¶ added in v0.31.0
Format formats the frame according to the fmt.Formatter interface.
%s source file %d source line %n function name %v equivalent to %s:%d
Format accepts flags that alter the printing of some verbs, as follows:
%+s function name and path of source file relative to the compile time GOPATH separated by \n\t (<funcname>\n\t<path>) %+v equivalent to %+s:%d
func (Frame) MarshalText ¶ added in v0.31.0
MarshalText formats a stacktrace Frame as a text string. The output is the same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
type Frames ¶ added in v0.47.0
type Frames []Frame
Frames is the ordered list of frames that make up a stack trace.
func (Frames) Format ¶ added in v0.47.0
Format formats the stack of Frames according to the fmt.Formatter interface.
%s lists source files for each Frame in the stack %v lists the source file and line number for each Frame in the stack
Format accepts flags that alter the printing of some verbs, as follows:
%+v Prints filename, function, and line number for each Frame in the stack.
type Opt ¶ added in v0.47.0
type Opt interface {
// contains filtered or unexported methods
}
Opt is a functional option. Use with Err or New.
type Skip ¶ added in v0.47.0
type Skip int
Skip is an Opt that can be passed to Err or New that indicates how many frames to skip when recording the stack trace. This is useful when wrapping errors in helper functions.
func handleErr(err error) error { slog.Default().Error("Oh noes", "err", err) return errz.Err(err, errz.Skip(1)) }
Skipping too many frames will panic.
type StackTrace ¶ added in v0.31.0
type StackTrace struct { // Error is the error value that resulted in this stack trace. Error error // Frames is the ordered list of frames that make up this stack trace. Frames Frames }
StackTrace contains a stack of Frames from innermost (newest) to outermost (oldest), as well as the error value that resulted in this stack trace.
func LastStack ¶ added in v0.47.0
func LastStack(err error) *StackTrace
LastStack returns the last of any stack trace(s) attached to err, or nil. Contrast with errz.Stacks, which returns all stack traces attached to any error in the chain. But if you only want to examine one stack, the final stack trace is usually the most interesting, which is why this function exists.
The returned StackTrace.Frames can be printed using fmt "%+v".
func Stacks ¶ added in v0.47.0
func Stacks(err error) []*StackTrace
Stacks returns all stack trace(s) attached to err. If err has been wrapped more than once, there may be multiple stack traces. Generally speaking, the final stack trace is the most interesting; you can use errz.LastStack if you're just interested in that one.
The returned StackTrace.Frames can be printed using fmt "%+v".
func (*StackTrace) LogValue ¶ added in v0.47.0
func (st *StackTrace) LogValue() slog.Value
LogValue implements slog.LogValuer.