My observation is that a root cause of an error is special, I usually only care about the first error and the last error in the chain except for logs.
In the end I disliked pkg/errors naming conventions and wrote my own small package.
A typical usage of my package in a server:
err := errors.Wrapf(err, "Additional context: %s", s)
...
if errors.RootCause(err) != sql.ErrNoRows {
Log("an error happend", "trace", errors.Trace(err))
}
A typical usage in a cli application is:
...
if err != nil {
// err.Error() only cares about the top level error and the root cause
fmt.Fprintf(os.Stderr, "%s\n", err.Error()) // 'Init failed' caused by 'File foo.cfg does not exist'
os.Exit(1)
}
One big lack I found is knowing the possible values of RootCause... A Go guru like analysis may help. especially a way to check reality with what the doc comments say.