Readers¶
The functions that get something back out of an error.
Every one of them uses the same tree traversal, which visits layers
outermost-first, depth-first through the members of an aggregate. That is why
none of these can disagree with another about what an error contains, and why all
of them see through a Join.
Hints and Details¶
Return every hint (or detail) in the tree, outermost first, de-duplicated.
An empty result is nil, not an empty slice.
err := errors.WithHint(errors.WithHint(errors.WithHint(
errors.New("x"), "inner"), "middle"), "outer")
errors.Hints(err) // [outer middle inner]
Identical strings collapse to one:
Empty strings are dropped rather than returned.
The GetAll aliases¶
Exactly Hints and Details, under the names the estate already called. They
exist so migrating a module is an import-path change rather than a port; prefer
the short names in new code.
FlattenHints and FlattenDetails¶
Join the list into one string, separated by \n--\n:
err := errors.WithHint(errors.WithHint(errors.New("x"), "b"), "a")
errors.FlattenHints(err) // "a\n--\nb"
The separator is deliberately distinctive so a flattened list can be split back out, which a newline-joined one cannot.
Attrs¶
Returns every structured attribute in the tree, outermost first. Duplicate keys
are preserved — see WithAttrs.
KindOf¶
Returns the error's identity: the outermost kind that is not one of this
package's own annotation wrappers. Returns "" when nothing in the tree declares
one.
var ErrNotFound = errors.NewSentinel("forge.not_found", "provider not found")
errors.KindOf(ErrNotFound) // "forge.not_found"
errors.KindOf(errors.New("x")) // "errors.basic"
errors.KindOf(fmt.Errorf("plain")) // ""
errors.KindOf(errors.Newf("reading %s", "f")) // ""
Annotating does not change the answer, which is the whole point:
err := errors.WithAttrs(
errors.WithHint(errors.WithStack(ErrNotFound), "h"),
slog.Int("n", 1),
)
errors.KindOf(err) // still "forge.not_found"
The outermost kind alone would report whichever annotation happened to be
applied last — errors.attrs for that error — which describes the package's
plumbing rather than the failure. The five structural kinds skipped are
errors.message, errors.stack, errors.hint, errors.detail and
errors.attrs.
errors.join is not skipped: an aggregate reports errors.join as its
identity.
This is what belongs in a log record's kind field and in OTEL's
exception.type.
StackOf¶
Returns the outermost stack in the tree, or nil. Outermost is the most
recently captured, and so the closest to where the error surfaced.
errors.StackOf(ErrNotFound) // nil — a sentinel carries none
errors.StackOf(errors.WithStack(ErrNotFound)) // the stack from the WithStack call
Render it with StackTrace.String().
Is, As, AsType and Unwrap¶
func Is(err, target error) bool
func As(err error, target any) bool
func AsType[E error](err error) (E, bool)
func Unwrap(err error) error
Straight passthroughs to the standard library's errors package, so this package
can be a drop-in import without a second import for the basics.
Prefer AsType over As — it needs no out-parameter: