errors

package module
v1.11.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2023 License: Apache-2.0 Imports: 19 Imported by: 6,023

README

cockroachdb/errors: Go errors with network portability

This library aims to be used as a drop-in replacement to github.com/pkg/errors and Go's standard errors package. It also provides network portability of error objects, in ways suitable for distributed systems with mixed-version software compatibility.

It also provides native and comprehensive support for PII-free details and an opt-in Sentry.io reporting mechanism that automatically formats error details and strips them of PII.

See also the design RFC.

Build Status Go Reference

Table of contents:

Features

Feature Go's <1.13 errors github.com/pkg/errors Go 1.13 errors/xerrors cockroachdb/errors
error constructors (New, Errorf etc)
error causes (Cause / Unwrap)
cause barriers (Opaque / Handled)
errors.As(), errors.Is()
automatic error wrap when format ends with : %w
standard wrappers with efficient stack trace capture
transparent protobuf encode/decode with forward compatibility
errors.Is() recognizes errors across the network
comprehensive support for PII-free reportable strings
support for both Cause() and Unwrap() go#31778
standard error reports to Sentry.io
wrappers to denote assertion failures
wrappers with issue tracker references
wrappers for user-facing hints and details
wrappers to attach secondary causes
wrappers to attach logtags details from context.Context
errors.FormatError(), Formatter, Printer (under construction)
errors.SafeFormatError(), SafeFormatter
wrapper-aware IsPermission(), IsTimeout(), IsExist(), IsNotExist()

"Forward compatibility" above refers to the ability of this library to recognize and properly handle network communication of error types it does not know about, for example when a more recent version of a software package sends a new error object to another system running an older version of the package.

How to use

  • construct errors with errors.New(), etc as usual, but also see the other error leaf constructors below.
  • wrap errors with errors.Wrap() as usual, but also see the other wrappers below.
  • test error identity with errors.Is() as usual. Unique in this library: this works even if the error has traversed the network! Also, errors.IsAny() to recognize two or more reference errors.
  • replace uses of os.IsPermission(), os.IsTimeout(), os.IsExist() and os.IsNotExist() by their analog in sub-package oserror so that they can peek through layers of wrapping.
  • access error causes with errors.UnwrapOnce() / errors.UnwrapAll() (note: errors.Cause() and errors.Unwrap() also provided for compatibility with other error packages).
  • encode/decode errors to protobuf with errors.EncodeError() / errors.DecodeError().
  • extract PII-free safe details with errors.GetSafeDetails().
  • extract human-facing hints and details with errors.GetAllHints()/errors.GetAllDetails() or errors.FlattenHints()/errors.FlattenDetails().
  • produce detailed Sentry.io reports with errors.BuildSentryReport() / errors.ReportError().
  • implement your own error leaf types and wrapper types:
    • implement the error and errors.Wrapper interfaces as usual.
    • register encode/decode functions: call errors.Register{Leaf,Wrapper}{Encoder,Decoder}() in a init() function in your package.
    • implement Format() that redirects to errors.FormatError().
    • see the section Building your own error types below.

What comes out of an error?

Error detail Error() and format %s/%q/%v format %+v GetSafeDetails() Sentry report via ReportError()
main message, eg New() visible visible yes (CHANGED IN v1.6) full (CHANGED IN v1.6)
wrap prefix, eg WithMessage() visible (as prefix) visible yes (CHANGED IN v1.6) full (CHANGED IN v1.6)
stack trace, eg WithStack() not visible simplified yes full
hint , eg WithHint() not visible visible no type only
detail, eg WithDetail() not visible visible no type only
assertion failure annotation, eg WithAssertionFailure() not visible visible no type only
issue links, eg WithIssueLink(), UnimplementedError() not visible visible yes full
safe details, eg WithSafeDetails() not visible not visible yes full
telemetry keys, eg. WithTelemetryKey() not visible visible yes full
secondary errors, eg. WithSecondaryError(), CombineErrors() not visible visible redacted, recursively redacted, recursively
barrier origins, eg. Handled() not visible visible redacted, recursively redacted, recursively
error domain, eg. WithDomain() not visible visible yes full
context tags, eg. WithContextTags() not visible visible keys visible, values redacted keys visible, values redacted

Available error leaves

An error leaf is an object that implements the error interface, but does not refer to another error via a Unwrap() or Cause() method.

  • New(string) error, Newf(string, ...interface{}) error, Errorf(string, ...interface{}) error: leaf errors with message

    • when to use: common error cases.
    • what it does: also captures the stack trace at point of call and redacts the provided message for safe reporting.
    • how to access the detail: Error(), regular Go formatting. Details in Sentry report.
    • see also: Section Error composition below. errors.NewWithDepth() variants to customize at which call depth the stack trace is captured.
  • AssertionFailedf(string, ...interface{}) error, NewAssertionFailureWithWrappedErrf(error, string, ...interface{}) error: signals an assertion failure / programming error.

    • when to use: when an invariant is violated; when an unreachable code path is reached.
    • what it does: also captures the stack trace at point of call, redacts the provided strings for safe reporting, prepares a hint to inform a human user.
    • how to access the detail: IsAssertionFailure()/HasAssertionFailure(), format with %+v, Safe details included in Sentry reports.
    • see also: Section Error composition below. errors.AssertionFailedWithDepthf() variant to customize at which call depth the stack trace is captured.
  • Handled(error) error, Opaque(error) error, HandledWithMessage(error, string) error: captures an error cause but make it invisible to Unwrap() / Is().

    • when to use: when a new error occurs while handling an error, and the original error must be "hidden".
    • what it does: captures the cause in a hidden field. The error message is preserved unless the ...WithMessage() variant is used.
    • how to access the detail: format with %+v, redacted details reported in Sentry reports.
  • UnimplementedError(IssueLink, string) error: captures a message string and a URL reference to an external resource to denote a feature that was not yet implemented.

    • when to use: to inform (human) users that some feature is not implemented yet and refer them to some external resource.
    • what it does: captures the message, URL and detail in a wrapper. The URL and detail are considered safe for reporting.
    • how to access the detail: errors.GetAllHints(), errors.FlattenHints(), format with %+v, URL and detail included in Sentry report (not the message).
    • see also: errors.WithIssueLink() below for errors that are not specifically about unimplemented features.

Available wrapper constructors

An error wrapper is an object that implements the error interface, and also refers to another error via an Unwrap() (preferred) and/or Cause() method.

All wrapper constructors can be applied safely to a nil error: they behave as no-ops in this case:

// The following:
// if err := foo(); err != nil {
//    return errors.Wrap(err, "foo")
// }
// return nil
//
// is not needed. Instead, you can use this:
return errors.Wrap(foo(), "foo")
  • Wrap(error, string) error, Wrapf(error, string, ...interface{}) error:

    • when to use: on error return paths.
    • what it does: combines WithMessage(), WithStack(), WithSafeDetails().
    • how to access the details: Error(), regular Go formatting. Details in Sentry report.
    • see also: Section Error composition below. WrapWithDepth() variants to customize at which depth the stack trace is captured.
  • WithSecondaryError(error, error) error: annotate an error with a secondary error.

    • when to use: when an additional error occurs in the code that is handling a primary error. Consider using errors.CombineErrors() instead (see below).
    • what it does: it captures the secondary error but hides it from errors.Is().
    • how to access the detail: format with %+v, redacted recursively in Sentry reports.
    • see also: errors.CombineErrors()
  • CombineErrors(error, error) error: combines two errors into one.

    • when to use: when two operations occur concurrently and either can return an error, and only one final error must be returned.
    • what it does: returns either of its arguments if the other is nil, otherwise calls WithSecondaryError().
    • how to access the detail: see WithSecondaryError() above.
  • Mark(error, error) error: gives the identity of one error to another error.

    • when to use: when a caller expects to recognize a sentinel error with errors.Is() but the callee provides a diversity of error messages.
    • what it does: it overrides the "error mark" used internally by errors.Is().
    • how to access the detail: format with %+v, Sentry reports.
  • WithStack(error) error: annotate with stack trace

    • when to use: usually not needed, use errors.Wrap()/errors.Wrapf() instead.

      Special cases:

      • when returning a sentinel, for example:

        var myErr = errors.New("foo")
        
        func myFunc() error {
          if ... {
             return errors.WithStack(myErr)
          }
        }
        
      • on error return paths, when not trivial but also not warranting a wrap. For example:

        err := foo()
        if err != nil {
          doSomething()
          if !somecond {
             return errors.WithStack(err)
          }
        }
        
    • what it does: captures (efficiently) a stack trace.

    • how to access the details: format with %+v, errors.GetSafeDetails(), Sentry reports. The stack trace is considered safe for reporting.

    • see also: WithStackDepth() to customize the call depth at which the stack trace is captured.

  • WithSafeDetails(error, string, ...interface{}) error: safe details for reporting.

    • when to use: probably never. Use errors.Wrap()/errors.Wrapf() instead.
    • what it does: saves some strings for safe reporting.
    • how to access the detail: format with %+v, errors.GetSafeDetails(), Sentry report.
  • WithMessage(error, string) error, WithMessagef(error, string, ...interface{}) error: message prefix.

    • when to use: probably never. Use errors.Wrap()/errors.Wrapf() instead.
    • what it does: adds a message prefix.
    • how to access the detail: Error(), regular Go formatting, Sentry Report.
  • WithDetail(error, string) error, WithDetailf(error, string, ...interface{}) error, user-facing detail with contextual information.

    • when to use: need to embark a message string to output when the error is presented to a developer.
    • what it does: captures detail strings.
    • how to access the detail: errors.GetAllDetails(), errors.FlattenDetails() (all details are preserved), format with %+v. Not included in Sentry reports.
  • WithHint(error, string) error, WithHintf(error, string, ...interface{}) error: user-facing detail with suggestion for action to take.

    • when to use: need to embark a message string to output when the error is presented to an end user.
    • what it does: captures hint strings.
    • how to access the detail: errors.GetAllHints(), errors.FlattenHints() (hints are de-duplicated), format with %+v. Not included in Sentry reports.
  • WithIssueLink(error, IssueLink) error: annotate an error with an URL and arbitrary string.

    • when to use: to refer (human) users to some external resources.
    • what it does: captures the URL and detail in a wrapper. Both are considered safe for reporting.
    • how to access the detail: errors.GetAllHints(), errors.FlattenHints(), errors.GetSafeDetails(), format with %+v, Sentry report.
    • see also: errors.UnimplementedError() to construct leaves (see previous section).
  • WithTelemetry(error, string) error: annotate an error with a key suitable for telemetry.

    • when to use: to gather strings during error handling, for capture in the telemetry sub-system of a server package.
    • what it does: captures the string. The telemetry key is considered safe for reporting.
    • how to access the detail: errors.GetTelemetryKeys(), errors.GetSafeDetails(), format with %+v, Sentry report.
  • WithDomain(error, Domain) error, HandledInDomain(error, Domain) error, HandledInDomainWithMessage(error, Domain, string) error (experimental): annotate an error with an origin package.

    • when to use: at package boundaries.
    • what it does: captures the identity of the error domain. Can be asserted with errors.EnsureNotInDomain(), errors.NotInDomain().
    • how to access the detail: format with %+v, Sentry report.
  • WithAssertionFailure(error) error: annotate an error as being an assertion failure.

    • when to use: probably never. Use errors.AssertionFailedf() and variants.
    • what it does: wraps the error with a special type. Triggers an auto-generated hint.
    • how to access the detail: IsAssertionFailure()/HasAssertionFailure(), errors.GetAllHints(), errors.FlattenHints(), format with %+v, Sentry report.
  • WithContextTags(error, context.Context) error: annotate an error with the k/v pairs attached to a context.Context instance with the logtags package.

    • when to use: when capturing/producing an error and a context.Context is available.
    • what it does: it captures the logtags.Buffer object in the wrapper.
    • how to access the detail: errors.GetContextTags(), format with %+v, Sentry reports.

Providing PII-free details

The library support PII-free strings essentially as follows:

  • by default, many strings included in an error object are considered to be PII-unsafe, and are stripped out when building a Sentry report.
  • some fields in the library are assumed to be PII-safe by default.
  • you can opt additional strings in to Sentry reports.

The following strings from this library are considered to be PII-free, and thus included in Sentry reports automatically:

  • the type of error objects,
  • stack traces (containing only file paths, line numbers, function names - arguments are not included),
  • issue tracker links (including URL and detail field),
  • telemetry keys,
  • error domains,
  • context tag keys,
  • the format string argument of Newf, AssertionFailedf, etc (the constructors ending with ...f()),
  • the type of the additional arguments passed to the ...f() constructors,
  • the value of specific argument types passed to the ...f() constructors, when known to be PII-safe. For details of which arguments are considered PII-free, see the redact package.

It is possible to opt additional in to Sentry reporting, using either of the following methods:

  • implement the errors.SafeDetailer interface, providing the SafeDetails() []string method on your error type.

  • enclose additional arguments passed to the ...f() constructors with errors.Safe(). For example: err := errors.Newf("my code: %d", errors.Safe(123)) — in this example, the value 123 will be included when a Sentry report is constructed.

    • it also makes it available via errors.GetSafeDetails()/GetAllSafeDetails().
    • the value 123 is also part of the main error message returned by Error().
  • attach additional arbitrary strings with errors.WithSafeDetails(error, string, ...interface{}) error and also use errors.Safe(). For example: err = errors.WithSafeDetails(err, "additional data: %s", errors.Safe("hello")).

    • in this example, the string "hello" will be included in Sentry reports.
    • however, it is not part of the main error message returned by Error().

For more details on how Sentry reports are built, see the report sub-package.

Building your own error types

You can create an error type as usual in Go: implement the error interface, and, if your type is also a wrapper, the errors.Wrapper interface (an Unwrap() method). You may also want to implement the Cause() method for backward compatibility with github.com/pkg/errors, if your project also uses that.

If your error type is a wrapper, you should implement a Format() method that redirects to errors.FormatError(), otherwise %+v will not work. Additionally, if your type has a payload not otherwise visible via Error(), you may want to implement errors.SafeFormatter. See making %+v work with your type below for details.

Finally, you may want your new error type to be portable across the network.

If your error type is a leaf, and already implements proto.Message (from gogoproto), you are all set and the errors library will use that automatically. If you do not or cannot implement proto.Message, or your error type is a wrapper, read on.

At a minimum, you will need a decoder function: while cockroachdb/errors already does a bunch of encoding/decoding work on new types automatically, the one thing it really cannot do on its own is instantiate a Go object using your new type.

Here is the simplest decode function for a new leaf error type and a new wrapper type:

// note: we use the gogoproto `proto` sub-package.
func yourDecode(_ string, _ []string, _ proto.Message) error {
   return &yourType{}
}

func init() {
   errors.RegisterLeafEncoder((*yourType)(nil), yourDecodeFunc)
}

func yourDecodeWrapper(cause error, _ string, _ []string, _ proto.Message) error {
   // Note: the library already takes care of encoding/decoding the cause.
   return &yourWrapperType{cause: cause}
}

func init() {
   errors.RegisterWrapperDecoder((*yourWrapperType)(nil), yourDecodeWrapper)
}

In the case where your type does not have any other field (empty struct for leafs, just a cause for wrappers), this is all you have to do.

(See the type withAssertionFailure in assert/assert.go for an example of this simple case.)

If your type does have additional fields, you may still not need a custom encoder. This is because the library automatically encodes/decodes the main error message and any safe strings that your error types makes available via the errors.SafeDetailer interface (the SafeDetails() method).

Say, for example, you have the following leaf type:

type myLeaf struct {
   code int
}

func (m *myLeaf) Error() string { return fmt.Sprintf("my error: %d" + m.code }

In that case, the library will automatically encode the result of calling Error(). This string will then be passed back to your decoder function as the first argument. This makes it possible to decode the code field exactly:

func myLeafDecoder(msg string, _ []string, _ proto.Message) error {
	codeS := strings.TrimPrefix(msg, "my error: ")
	code, _ := strconv.Atoi(codeS)
	// Note: error handling for strconv is omitted here to simplify
	// the explanation. If your decoder function should fail, simply
	// return a `nil` error object (not another unrelated error!).
	return &myLeaf{code: code}
}

Likewise, if your fields are PII-free, they are safe to expose via the errors.SafeDetailer interface. Those strings also get encoded automatically, and get passed to the decoder function as the second argument.

For example, say you have the following leaf type:

type myLeaf struct {
   // both fields are PII-free.
   code int
   tag string
}

func (m *myLeaf) Error() string { ... }

Then you can expose the fields as safe details as follows:

func (m *myLeaf) SafeDetails() []string {
  return []string{fmt.Sprintf("%d", m.code), m.tag}
}

(If the data is PII-free, then it is good to do this in any case: it enables any network system that receives an error of your type, but does not know about it, to still produce useful Sentry reports.)

Once you have this, the decode function receives the strings and you can use them to re-construct the error:

func myLeafDecoder(_ string, details []string, _ proto.Message) error {
    // Note: you may want to test the length of the details slice
	// is correct.
    code, _ := strconv.Atoi(details[0])
    tag := details[1]
	return &myLeaf{code: code, tag: tag}
}

(For an example, see the withTelemetry type in telemetry/with_telemetry.go.)

The only case where you need a custom encoder is when your error type contains some fields that are not reflected in the error message (so you can't extract them back from there), and are not PII-free and thus cannot be reported as "safe details".

To take inspiration from examples, see the following types in the library that need a custom encoder:

Making %+v work with your type

In short:

  • When in doubt, you should always implement the fmt.Formatter interface (Format(fmt.State, rune)) on your custom error types, exactly as follows:

    func (e *yourType) Format(s *fmt.State, verb rune) { errors.FormatError(e, s, verb) }
    

    (If you do not provide this redirection for your own custom wrapper type, this will disable the recursive application of the %+v flag to the causes chained from your wrapper.)

  • You may optionally implement the errors.SafeFormatter interface: SafeFormatError(p errors.Printer) (next error). This is optional, but should be done when some details are not included by Error() and should be emitted upon %+v.

The example withHTTPCode wrapper included in the source tree achieves this as follows:

// Format() implements fmt.Formatter, is required until Go knows about FormatError.
func (w *withHTTPCode) Format(s fmt.State, verb rune) { errors.FormatError(w, s, verb) }

// FormatError() formats the error.
func (w *withHTTPCode) SafeFormatError(p errors.Printer) (next error) {
	// Note: no need to print out the cause here!
	// FormatError() knows how to do this automatically.
	if p.Detail() {
		p.Printf("http code: %d", errors.Safe(w.code))
	}
	return w.cause
}

Technical details follow:

  • The errors library follows the Go 2 proposal.

  • At some point in the future, Go's standard fmt library will learn how to recognize error wrappers, and how to use the errors.Formatter interface automatically. Until then, you must ensure that you also implement a Format() method (from fmt.Formatter) that redirects to errors.FormatError.

    Note: you may implement fmt.Formatter (Format() method) in this way without implementing errors.Formatter (a FormatError() method). In that case, errors.FormatError will use a separate code path that does "the right thing", even for wrappers.

  • The library provides an implementation of errors.FormatError(), modeled after the same function in Go 2. This is responsible for printing out error details, and knows how to present a chain of causes in a semi-structured format upon formatting with %+v.

Ensuring errors.Is works when errors/packages are renamed

If a Go package containing a custom error type is renamed, or the error type itself is renamed, and errors of this type are transported over the network, then another system with a different code layout (e.g. running a different version of the software) may not be able to recognize the error any more via errors.Is.

To ensure that network portability continues to work across multiple software versions, in the case error types get renamed or Go packages get moved / renamed / etc, the server code must call errors.RegisterTypeMigration() from e.g. an init() function.

Example use:

 previousPath := "github.com/old/path/to/error/package"
 previousTypeName := "oldpackage.oldErrorName"
 newErrorInstance := &newTypeName{...}
 errors.RegisterTypeMigration(previousPath, previousTypeName, newErrorInstance)

Error composition (summary)

Constructor Composes
New NewWithDepth (see below)
Errorf = Newf
Newf NewWithDepthf (see below)
WithMessage custom wrapper with message prefix and knowledge of safe strings
Wrap WrapWithDepth (see below)
Wrapf WrapWithDepthf (see below)
AssertionFailed AssertionFailedWithDepthf (see below)
NewWithDepth custom leaf with knowledge of safe strings + WithStackDepth (see below)
NewWithDepthf custom leaf with knowledge of safe strings + WithSafeDetails + WithStackDepth
WithMessagef custom wrapper with message prefix and knowledge of safe strings
WrapWithDepth WithMessage + WithStackDepth
WrapWithDepthf WithMessagef + WithStackDepth
AssertionFailedWithDepthf NewWithDepthf + WithAssertionFailure
NewAssertionErrorWithWrappedErrf HandledWithMessagef (barrier) + WrapWithDepthf + WithAssertionFailure
Join JoinWithDepth (see below)
JoinWithDepth multi-cause wrapper + WithStackDepth

API (not constructing error objects)

The following is a summary of the non-constructor API functions, grouped by category. Detailed documentation can be found at: https://pkg.go.dev/github.com/cockroachdb/errors

// Access causes.
func UnwrapAll(err error) error
func UnwrapOnce(err error) error
func Cause(err error) error // compatibility
func Unwrap(err error) error // compatibility
type Wrapper interface { ... } // compatibility

// Error formatting.
type Formatter interface { ... } // compatibility, not recommended
type SafeFormatter interface { ... }
type Printer interface { ... }
func FormatError(err error, s fmt.State, verb rune)
func Formattable(err error) fmt.Formatter

// Identify errors.
func Is(err, reference error) bool
func IsAny(err error, references ...error) bool
func If(err error, pred func(err error) (interface{}, bool)) (interface{}, bool)
func As(err error, target interface{}) bool

// Encode/decode errors.
type EncodedError // this is protobuf-encodable
func EncodeError(ctx context.Context, err error) EncodedError
func DecodeError(ctx context.Context, enc EncodedError) error

// Register encode/decode functions for custom/new error types.
func RegisterLeafDecoder(typeName TypeKey, decoder LeafDecoder)
func RegisterLeafEncoder(typeName TypeKey, encoder LeafEncoder)
func RegisterWrapperDecoder(typeName TypeKey, decoder WrapperDecoder)
func RegisterWrapperEncoder(typeName TypeKey, encoder WrapperEncoder)
func RegisterWrapperEncoderWithMessageOverride (typeName TypeKey, encoder WrapperEncoderWithMessageOverride)
func RegisterMultiCauseEncoder(theType TypeKey, encoder MultiCauseEncoder)
func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder)
type LeafEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message)
type LeafDecoder = func(ctx context.Context, msg string, safeDetails []string, payload proto.Message) error
type WrapperEncoder = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message)
type WrapperEncoderWithMessageOverride = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message, overrideError bool)
type WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, safeDetails []string, payload proto.Message) error
type MultiCauseEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message)
type MultiCauseDecoder = func(ctx context.Context, causes []error, msgPrefix string, safeDetails []string, payload proto.Message) error

// Registering package renames for custom error types.
func RegisterTypeMigration(previousPkgPath, previousTypeName string, newType error)

// Sentry reports.
func BuildSentryReport(err error) (*sentry.Event, map[string]interface{})
func ReportError(err error) (string)

// Stack trace captures.
func GetOneLineSource(err error) (file string, line int, fn string, ok bool)
type ReportableStackTrace = sentry.StackTrace
func GetReportableStackTrace(err error) *ReportableStackTrace

// Safe (PII-free) details.
type SafeDetailPayload struct { ... }
func GetAllSafeDetails(err error) []SafeDetailPayload
func GetSafeDetails(err error) (payload SafeDetailPayload)

// Obsolete APIs.
type SafeMessager interface { ... }
func Redact(r interface{}) string

// Aliases redact.Safe.
func Safe(v interface{}) SafeMessager

// Assertion failures.
func HasAssertionFailure(err error) bool
func IsAssertionFailure(err error) bool

// User-facing details and hints.
func GetAllDetails(err error) []string
func FlattenDetails(err error) string
func GetAllHints(err error) []string
func FlattenHints(err error) string

// Issue links / URL wrappers.
func HasIssueLink(err error) bool
func IsIssueLink(err error) bool
func GetAllIssueLinks(err error) (issues []IssueLink)

// Unimplemented errors.
func HasUnimplementedError(err error) bool
func IsUnimplementedError(err error) bool

// Telemetry keys.
func GetTelemetryKeys(err error) []string

// Domain errors.
type Domain
const NoDomain Domain
func GetDomain(err error) Domain
func NamedDomain(domainName string) Domain
func PackageDomain() Domain
func PackageDomainAtDepth(depth int) Domain
func EnsureNotInDomain(err error, constructor DomainOverrideFn, forbiddenDomains ...Domain) error
func NotInDomain(err error, doms ...Domain) bool

// Context tags.
func GetContextTags(err error) []*logtags.Buffer

Documentation

Index

Constants

View Source
const UnimplementedErrorHint = issuelink.UnimplementedErrorHint

UnimplementedErrorHint is the hint emitted upon unimplemented errors.

Variables

This section is empty.

Functions

func As added in v1.2.0

func As(err error, target interface{}) bool

As finds the first error in err's chain that matches the type to which target points, and if so, sets the target to its value and returns true. An error matches a type if it is assignable to the target type, or if it has a method As(interface{}) bool such that As(target) returns true. As will panic if target is not a non-nil pointer to a type which implements error or is of interface type.

The As method should set the target to its value and return true if err matches the type to which target points.

Note: this implementation differs from that of xerrors as follows: - it also supports recursing through causes with Cause(). - if it detects an API use error, its panic object is a valid error.

func AssertionFailedWithDepthf

func AssertionFailedWithDepthf(depth int, format string, args ...interface{}) error

AssertionFailedWithDepthf creates an internal error with a stack trace collected at the specified depth. See the doc of `AssertionFailedf()` for more details.

func AssertionFailedf

func AssertionFailedf(format string, args ...interface{}) error

AssertionFailedf creates an internal error.

Detail is shown: - via `errors.GetSafeDetails()`, shows redacted strings. - when formatting with `%+v`. - in Sentry reports.

func BuildSentryReport

func BuildSentryReport(err error) (*sentry.Event, map[string]interface{})

BuildSentryReport builds the components of a sentry report. This can be used instead of ReportError() below to use additional custom conditions in the reporting or add additional reporting tags.

The Sentry Event is populated for maximal utility when exploited in the Sentry.io web interface and database.

A Sentry report is displayed visually in the Sentry UI as follows:

////////////// Title: (1) some prefix in bold (2) one line for a stack trace (3) a single-line subtitle

(4) the tags, as a tag soup (concatenated in a single paragraph, unsorted)

(5) a "message"

(6) zero or more "exceptions", each composed of:

(7) a bold title
(8) some freeform text
(9) a stack trace

(10) metadata fields: environment, arch, etc

(11) "Additional data" fields

(12) SDK version ///////////////

These visual items map to the Sentry Event object as follows:

(1) the Type field of the 1st Exception object, if any

otherwise the Message field

(2) the topmost entry from the Stacktrace field of the 1st Exception object, if any (3) the Value field of the 1st Exception object, if any, unwrapped as a single line (4) the Tags field (5) the Message field (7) the Type field (same as (1) for 1st exception) (8) the Value field (same as (3) for 1st exception) (9) the Stacktrace field (input to (2) on 1st exception) (10) the other fields on the Event object (11) the Extra field

(Note how the top-level title fields (1) (3) are unrelated to the Message field in the event, which is surprising!)

Given this mapping, an error object is decomposed as follows:

(1)/(7): <filename>:<lineno> (<functionname>) (3)/(8): <error type>: <first safe detail line, if any> (4): not populated in this function, caller is to manage this (5): detailed structure of the entire error object, with references to "additional data"

and additional "exception" objects

(9): generated from innermost stack trace (6): every exception object after the 1st reports additional stack trace contexts (11): "additional data" populated from safe detail payloads

If there is no stack trace in the error, a synthetic Exception object is still produced to provide visual detail in the Sentry UI.

Note that if a layer in the error has both a stack trace (ie provides the `StackTrace()` interface) and also safe details (`SafeDetails()`) other than the stack trace, only the stack trace is included in the Sentry report. This does not affect error types provided by the library, but could impact error types defined by 3rd parties. This limitation may be lifted in a later version.

func Cause

func Cause(err error) error

Cause aliases UnwrapAll() for compatibility with github.com/pkg/errors.

func CombineErrors added in v1.1.0

func CombineErrors(err, otherErr error) error

CombineErrors returns err, or, if err is nil, otherErr. if err is non-nil, otherErr is attached as secondary error. See the documentation of `WithSecondaryError()` for details.

func DecodeError

func DecodeError(ctx context.Context, enc EncodedError) error

DecodeError decodes an error.

func EnsureNotInDomain

func EnsureNotInDomain(err error, constructor DomainOverrideFn, forbiddenDomains ...Domain) error

EnsureNotInDomain checks whether the error is in the given domain(s). If it is, the given constructor if provided is called to construct an alternate error. If no error constructor is provided, a new barrier is constructed automatically using the first provided domain as new domain. The original error message is preserved.

func Errorf

func Errorf(format string, args ...interface{}) error

Errorf aliases Newf().

func FlattenDetails

func FlattenDetails(err error) string

FlattenDetails retrieves the details as per GetAllDetails() and concatenates them into a single string.

func FlattenHints

func FlattenHints(err error) string

FlattenHints retrieves the hints as per GetAllHints() and concatenates them into a single string.

func FormatError added in v1.2.0

func FormatError(err error, s fmt.State, verb rune)

FormatError formats an error according to s and verb. This is a helper meant for use when implementing the fmt.Formatter interface on custom error objects.

If the error implements errors.Formatter, FormatError calls its FormatError method of f with an errors.Printer configured according to s and verb, and writes the result to s.

Otherwise, if it is a wrapper, FormatError prints out its error prefix, then recurses on its cause.

Otherwise, its Error() text is printed.

func Formattable added in v1.7.0

func Formattable(err error) fmt.Formatter

Formattable wraps an error into a fmt.Formatter which will provide "smart" formatting even if the outer layer of the error does not implement the Formatter interface.

func GetAllDetails

func GetAllDetails(err error) []string

GetAllDetails retrieves the details from the error using in post-order traversal.

func GetAllHints

func GetAllHints(err error) []string

GetAllHints retrieves the hints from the error using in post-order traversal. The hints are de-duplicated. Assertion failures, issue links and unimplemented errors are detected and receive standard hints.

func GetContextTags added in v1.1.0

func GetContextTags(err error) []*logtags.Buffer

GetContextTags retrieves the k/v pairs stored in the error. The sets are returned from outermost to innermost level of cause. The returned logtags.Buffer only know about the string representation of the values originally captured by the error.

func GetOneLineSource

func GetOneLineSource(err error) (file string, line int, fn string, ok bool)

GetOneLineSource extracts the file/line/function information of the topmost caller in the innermost recorded stack trace. The filename is simplified to remove the path prefix.

This is used e.g. to populate the "source" field in PostgreSQL errors in CockroachDB.

func GetTelemetryKeys

func GetTelemetryKeys(err error) []string

GetTelemetryKeys retrieves the (de-duplicated) set of all telemetry keys present in the direct causal chain of the error. The keys may not be sorted.

func HandleAsAssertionFailure added in v1.2.3

func HandleAsAssertionFailure(origErr error) error

HandleAsAssertionFailure hides an error and turns it into an assertion failure. Both details from the original error and the context of the caller are preserved. The original error is not visible as cause any more. The original error message is preserved. See the doc of `AssertionFailedf()` for more details.

func HandleAsAssertionFailureDepth added in v1.2.3

func HandleAsAssertionFailureDepth(depth int, origErr error) error

HandleAsAssertionFailureDepth is like HandleAsAssertionFailure but the depth at which the call stack is captured can be specified.

func Handled

func Handled(err error) error

Handled swallows the provided error and hides it from the Cause()/Unwrap() interface, and thus the Is() facility that identifies causes. However, it retains it for the purpose of printing the error out (e.g. for troubleshooting). The error message is preserved in full.

Detail is shown: - via `errors.GetSafeDetails()`, shows details from hidden error. - when formatting with `%+v`. - in Sentry reports.

func HandledInDomain

func HandledInDomain(err error, domain Domain) error

HandledInDomain creates an error in the given domain and retains the details of the given original error as context for debugging. The original error is hidden and does not become a "cause" for the new error. The original's error _message_ is preserved.

See the documentation of `WithDomain()` and `errors.Handled()` for details.

func HandledInDomainWithMessage

func HandledInDomainWithMessage(err error, domain Domain, msg string) error

HandledInDomainWithMessage is like HandledWithMessage but with a domain.

func HandledWithMessage

func HandledWithMessage(err error, msg string) error

HandledWithMessage is like Handled except the message is overridden. This can be used e.g. to hide message details or to prevent downstream code to make assertions on the message's contents.

func HasAssertionFailure

func HasAssertionFailure(err error) bool

HasAssertionFailure returns true if the error or any of its causes is an assertion failure annotation.

func HasInterface added in v1.5.0

func HasInterface(err error, referenceInterface interface{}) bool

HasInterface returns true if err contains an error which implements the interface pointed to by referenceInterface. The type of referenceInterface must be a pointer to an interface type. If referenceInterface is not a pointer to an interface, this function will panic.

func HasIssueLink(err error) bool

HasIssueLink returns true iff the error or one of its causes has a linked issue payload.

func HasType added in v1.4.0

func HasType(err, referenceType error) bool

HasType returns true iff err contains an error whose concrete type matches that of referenceType.

func HasUnimplementedError

func HasUnimplementedError(err error) bool

HasUnimplementedError returns iff if err or its cause is an unimplemented error.

func If

func If(err error, pred func(err error) (interface{}, bool)) (interface{}, bool)

If iterates on the error's causal chain and returns a predicate's return value the first time the predicate returns true.

Note: if any of the error types has been migrated from a previous package location or a different type, ensure that RegisterTypeMigration() was called prior to If().

func Is

func Is(err, reference error) bool

Is determines whether one of the causes of the given error or any of its causes is equivalent to some reference error.

As in the Go standard library, an error is considered to match a reference error if it is equal to that target or if it implements a method Is(error) bool such that Is(reference) returns true.

Note: the inverse is not true - making an Is(reference) method return false does not imply that errors.Is() also returns false. Errors can be equal because their network equality marker is the same. To force errors to appear different to Is(), use errors.Mark().

Note: if any of the error types has been migrated from a previous package location or a different type, ensure that RegisterTypeMigration() was called prior to Is().

func IsAny

func IsAny(err error, references ...error) bool

IsAny is like Is except that multiple references are compared.

Note: if any of the error types has been migrated from a previous package location or a different type, ensure that RegisterTypeMigration() was called prior to IsAny().

func IsAssertionFailure

func IsAssertionFailure(err error) bool

IsAssertionFailure returns true if the error (not its causes) is an assertion failure annotation. Consider using markers.If or HasAssertionFailure to test both the error and its causes.

func IsIssueLink(err error) bool

IsIssueLink returns true iff the error (not its causes) has a linked issue payload.

func IsUnimplementedError

func IsUnimplementedError(err error) bool

IsUnimplementedError returns iff if err is an unimplemented error.

func Join added in v1.10.1

func Join(errs ...error) error

Join returns an error that wraps the given errors. Any nil error values are discarded. Join returns nil if errs contains no non-nil values. The error formats as the concatenation of the strings obtained by calling the Error method of each element of errs, with a newline between each string. A stack trace is also retained.

func JoinWithDepth added in v1.10.1

func JoinWithDepth(depth int, errs ...error) error

JoinWithDepth is like Join but the depth at which the call stack is captured can be specified.

func Mark

func Mark(err error, reference error) error

Mark creates an explicit mark for the given error, using the same mark as some reference error.

Note: if any of the error types has been migrated from a previous package location or a different type, ensure that RegisterTypeMigration() was called prior to Mark().

func New

func New(msg string) error

New creates an error with a simple error message. A stack trace is retained.

Note: the message string is assumed to not contain PII and is included in Sentry reports. Use errors.Newf("%s", <unsafestring>) for errors strings that may contain PII information.

Detail output: - message via `Error()` and formatting using `%v`/`%s`/`%q`. - everything when formatting with `%+v`. - stack trace and message via `errors.GetSafeDetails()`. - stack trace and message in Sentry reports.

func NewAssertionErrorWithWrappedErrf

func NewAssertionErrorWithWrappedErrf(origErr error, format string, args ...interface{}) error

NewAssertionErrorWithWrappedErrf wraps an error and turns it into an assertion error. Both details from the original error and the context of the caller are preserved. The original error is not visible as cause any more. The original error message is preserved. See the doc of `AssertionFailedf()` for more details.

func NewWithDepth

func NewWithDepth(depth int, msg string) error

NewWithDepth is like New() except the depth to capture the stack trace is configurable. See the doc of `New()` for more details.

func NewWithDepthf

func NewWithDepthf(depth int, format string, args ...interface{}) error

NewWithDepthf is like Newf() except the depth to capture the stack trace is configurable. See the doc of `New()` for more details.

func Newf

func Newf(format string, args ...interface{}) error

Newf creates an error with a formatted error message. A stack trace is retained.

Note: the format string is assumed to not contain PII and is included in Sentry reports. Use errors.Newf("%s", <unsafestring>) for errors strings that may contain PII information.

See the doc of `New()` for more details.

func NotInDomain

func NotInDomain(err error, doms ...Domain) bool

NotInDomain returns true if and only if the error's domain is not one of the specified domains.

func Opaque added in v1.1.0

func Opaque(err error) error

Opaque aliases barrier.Handled(), for compatibility with xerrors.

func Redact

func Redact(r interface{}) string

Redact returns a redacted version of the supplied item that is safe to use in anonymized reporting.

NB: this interface is obsolete. Use redact.Sprint() directly.

func RegisterLeafDecoder

func RegisterLeafDecoder(typeName TypeKey, decoder LeafDecoder)

RegisterLeafDecoder can be used to register new leaf error types to the library. Registered types will be decoded using their own Go type when an error is decoded. Wrappers that have not been registered will be decoded using the opaqueLeaf type.

Note: if the error type has been migrated from a previous location or a different type, ensure that RegisterTypeMigration() was called prior to RegisterLeafDecoder().

func RegisterLeafEncoder

func RegisterLeafEncoder(typeName TypeKey, encoder LeafEncoder)

RegisterLeafEncoder can be used to register new leaf error types to the library. Registered types will be encoded using their own Go type when an error is encoded. Wrappers that have not been registered will be encoded using the opaqueLeaf type.

Note: if the error type has been migrated from a previous location or a different type, ensure that RegisterTypeMigration() was called prior to RegisterLeafEncoder().

func RegisterMultiCauseDecoder added in v1.10.1

func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder)

RegisterMultiCauseDecoder can be used to register new multi-cause wrapper types to the library. Registered wrappers will be decoded using their own Go type when an error is decoded. Multi-cause wrappers that have not been registered will be decoded using the opaqueWrapper type.

func RegisterMultiCauseEncoder added in v1.10.1

func RegisterMultiCauseEncoder(typeName TypeKey, encoder MultiCauseEncoder)

RegisterMultiCauseEncoder can be used to register new multi-cause error types to the library. Registered types will be encoded using their own Go type when an error is encoded. Multi-cause wrappers that have not been registered will be encoded using the opaqueWrapper type.

func RegisterTypeMigration added in v1.8.0

func RegisterTypeMigration(previousPkgPath, previousTypeName string, newType error)

RegisterTypeMigration tells the library that the type of the error given as 3rd argument was previously known with type previousTypeName, located at previousPkgPath.

The value of previousTypeName must be the result of calling reflect.TypeOf(err).String() on the original error object. This is usually composed as follows:

[*]<shortpackage>.<errortype>

For example, Go's standard error type has name "*errors.errorString". The asterisk indicates that `errorString` implements the `error` interface via pointer receiver.

Meanwhile, the singleton error type context.DeadlineExceeded has name "context.deadlineExceededError", without asterisk because the type implements `error` by value.

Remember that the short package name inside the error type name and the last component of the package path can be different. This is why they must be specified separately.

func RegisterWrapperDecoder

func RegisterWrapperDecoder(typeName TypeKey, decoder WrapperDecoder)

RegisterWrapperDecoder can be used to register new wrapper types to the library. Registered wrappers will be decoded using their own Go type when an error is decoded. Wrappers that have not been registered will be decoded using the opaqueWrapper type.

Note: if the error type has been migrated from a previous location or a different type, ensure that RegisterTypeMigration() was called prior to RegisterWrapperDecoder().

func RegisterWrapperEncoder

func RegisterWrapperEncoder(typeName TypeKey, encoder WrapperEncoder)

RegisterWrapperEncoder can be used to register new wrapper types to the library. Registered wrappers will be encoded using their own Go type when an error is encoded. Wrappers that have not been registered will be encoded using the opaqueWrapper type.

Note: if the error type has been migrated from a previous location or a different type, ensure that RegisterTypeMigration() was called prior to RegisterWrapperEncoder().

func RegisterWrapperEncoderWithMessageType added in v1.10.1

func RegisterWrapperEncoderWithMessageType(typeName TypeKey, encoder WrapperEncoderWithMessageType)

RegisterWrapperEncoderWithMessageType can be used to register new wrapper types to the library. These wrappers can optionally override the child error messages with their own error string instead of relying on iterative concatenation. Registered wrappers will be encoded using their own Go type when an error is encoded. Wrappers that have not been registered will be encoded using the opaqueWrapper type.

Note: if the error type has been migrated from a previous location or a different type, ensure that RegisterTypeMigration() was called prior to RegisterWrapperEncoder().

func ReportError

func ReportError(err error) string

ReportError reports the given error to Sentry. The caller is responsible for checking whether telemetry is enabled, and calling the sentry.Flush() function to wait for the report to be uploaded. (By default, Sentry submits reports asynchronously.)

Note: an empty 'eventID' can be returned which signifies that the error was not reported. This can occur when Sentry client hasn't been properly configured or Sentry client decided to not report the error (due to configured sampling rate, callbacks, Sentry's event processors, etc).

func Safe

func Safe(v interface{}) redact.SafeValue

Safe wraps the given object into an opaque struct that implements SafeMessager: its contents can be included as-is in PII-free strings in error objects and reports.

NB: this is obsolete. Use redact.Safe instead.

func SetWarningFn added in v1.2.2

func SetWarningFn(fn func(context.Context, string, ...interface{}))

SetWarningFn enables configuration of the warning function.

func UnimplementedError

func UnimplementedError(issueLink IssueLink, msg string) error

UnimplementedError creates a new leaf error that indicates that some feature was not (yet) implemented.

Detail is shown: - via `errors.GetSafeDetails()` - when formatting with `%+v`. - in Sentry reports. - via `errors.GetAllHints()` / `errors.FlattenHints()`

func UnimplementedErrorf

func UnimplementedErrorf(issueLink IssueLink, format string, args ...interface{}) error

UnimplementedErrorf creates a new leaf error that indicates that some feature was not (yet) implemented. The message is formatted.

func Unwrap added in v1.1.0

func Unwrap(err error) error

Unwrap aliases UnwrapOnce() for compatibility with xerrors.

func UnwrapAll

func UnwrapAll(err error) error

UnwrapAll accesses the root cause object of the error. If the error has no cause (leaf error), it is returned directly.

func UnwrapOnce

func UnwrapOnce(err error) error

UnwrapOnce accesses the direct cause of the error if any, otherwise returns nil.

It supports both errors implementing causer (`Cause()` method, from github.com/pkg/errors) and `Wrapper` (`Unwrap()` method, from the Go 2 error proposal).

func WithAssertionFailure

func WithAssertionFailure(err error) error

WithAssertionFailure decorates the error with an assertion failure marker. This is not intended to be used directly (see AssertionFailed() for further decoration).

Detail is shown: - when formatting with `%+v`. - in Sentry reports.

func WithContextTags added in v1.1.0

func WithContextTags(err error, ctx context.Context) error

WithContextTags captures the k/v pairs stored in the context via the `logtags` package and annotates them on the error.

Only the strong representation of values remains available. This is because the library cannot guarantee that the underlying value is preserved across the network. To avoid creating a stateful interface (where the user code needs to know whether an error has traveled through the network or not), the library restricts access to the value part as strings. See GetContextTags() below.

Detail is shown: - via `errors.GetSafeDetails()`. - via `GetContextTags()` below. - when formatting with `%+v`. - in Sentry reports.

func WithDetail

func WithDetail(err error, msg string) error

WithDetail decorates an error with a textual detail. The detail may contain PII and thus will not reportable. The suggested use case for detail is to augment errors with information useful for debugging.

Detail is shown: - when formatting with `%+v`. - with `GetAllDetails()` / `FlattenDetails()` below.

Note: the detail does not appear in the main error message returned with Error(). Use GetAllDetails() or FlattenDetails() to retrieve it.

func WithDetailf

func WithDetailf(err error, format string, args ...interface{}) error

WithDetailf is a helper that formats the detail string. See the documentation of WithDetail() for details.

func WithDomain

func WithDomain(err error, domain Domain) error

WithDomain wraps an error so that it appears to come from the given domain.

Domain is shown: - via `errors.GetSafeDetails()`. - when formatting with `%+v`. - in Sentry reports.

func WithHint

func WithHint(err error, msg string) error

WithHint decorates an error with a textual hint. The hint may contain PII and thus will not reportable. The suggested use case for hint is to relay information to end users.

Hint is shown: - when formatting with `%+v`. - with `GetAllHints()` / `FlattenHints()` below.

Note: the hint does not appear in the main error message returned with Error(). Use GetAllHints() or FlattenHints() to retrieve it.

func WithHintf

func WithHintf(err error, format string, args ...interface{}) error

WithHintf is a helper that formats the hint. See the documentation of WithHint() for details.

func WithIssueLink(err error, issue IssueLink) error

WithIssueLink adds an annotation to a know issue on a web issue tracker.

The url and detail strings may contain PII and will be considered reportable.

Detail is shown: - via `errors.GetSafeDetails()` - when formatting with `%+v`. - in Sentry reports. - via `errors.GetAllHints()` / `errors.FlattenHints()`

func WithMessage

func WithMessage(err error, msg string) error

WithMessage annotates err with a new message. If err is nil, WithMessage returns nil. The message is considered safe for reporting and is included in Sentry reports.

func WithMessagef

func WithMessagef(err error, format string, args ...interface{}) error

WithMessagef annotates err with the format specifier. If err is nil, WithMessagef returns nil. The message is formatted as per redact.Sprintf, to separate safe and unsafe strings for Sentry reporting.

func WithSafeDetails

func WithSafeDetails(err error, format string, args ...interface{}) error

WithSafeDetails annotates an error with the given reportable details. The format is made available as a PII-free string, alongside with a PII-free representation of every additional argument. Arguments can be reported as-is (without redaction) by wrapping them using the Safe() function.

If the format is empty and there are no arguments, the error argument is returned unchanged.

Detail is shown: - via `errors.GetSafeDetails()` - when formatting with `%+v`. - in Sentry reports.

func WithSecondaryError

func WithSecondaryError(err error, additionalErr error) error

WithSecondaryError enhances the error given as first argument with an annotation that carries the error given as second argument. The second error does not participate in cause analysis (Is, etc) and is only revealed when printing out the error or collecting safe (PII-free) details for reporting.

If additionalErr is nil, the first error is returned as-is.

Tip: consider using CombineErrors() below in the general case.

Detail is shown: - via `errors.GetSafeDetails()`, shows details from secondary error. - when formatting with `%+v`. - in Sentry reports.

func WithStack

func WithStack(err error) error

WithStack annotates err with a stack trace at the point WithStack was called.

Detail is shown: - via `errors.GetSafeDetails()` - when formatting with `%+v`. - in Sentry reports. - when innermost stack capture, with `errors.GetOneLineSource()`.

func WithStackDepth

func WithStackDepth(err error, depth int) error

WithStackDepth annotates err with a stack trace starting from the given call depth. The value zero identifies the caller of WithStackDepth itself. See the documentation of WithStack() for more details.

func WithTelemetry

func WithTelemetry(err error, keys ...string) error

WithTelemetry annotates err with the given telemetry key(s). The telemetry keys must be PII-free.

Detail is shown: - via `errors.GetSafeDetails()`. - via `GetTelemetryKeys()` below. - when formatting with `%+v`. - in Sentry reports.

func Wrap

func Wrap(err error, msg string) error

Wrap wraps an error with a message prefix. A stack trace is retained.

Note: the prefix string is assumed to not contain PII and is included in Sentry reports. Use errors.Wrapf(err, "%s", <unsafestring>) for errors strings that may contain PII information.

Detail output: - original error message + prefix via `Error()` and formatting using `%v`/`%s`/`%q`. - everything when formatting with `%+v`. - stack trace and message via `errors.GetSafeDetails()`. - stack trace and message in Sentry reports.

func WrapWithDepth

func WrapWithDepth(depth int, err error, msg string) error

WrapWithDepth is like Wrap except the depth to capture the stack trace is configurable. The the doc of `Wrap()` for more details.

func WrapWithDepthf

func WrapWithDepthf(depth int, err error, format string, args ...interface{}) error

WrapWithDepthf is like Wrapf except the depth to capture the stack trace is configurable. The the doc of `Wrapf()` for more details.

func Wrapf

func Wrapf(err error, format string, args ...interface{}) error

Wrapf wraps an error with a formatted message prefix. A stack trace is also retained. If the format is empty, no prefix is added, but the extra arguments are still processed for reportable strings.

Note: the format string is assumed to not contain PII and is included in Sentry reports. Use errors.Wrapf(err, "%s", <unsafestring>) for errors strings that may contain PII information.

Detail output: - original error message + prefix via `Error()` and formatting using `%v`/`%s`/`%q`. - everything when formatting with `%+v`. - stack trace, format, and redacted details via `errors.GetSafeDetails()`. - stack trace, format, and redacted details in Sentry reports.

Types

type Domain

type Domain = domains.Domain

Domain is the type of a domain annotation.

const NoDomain Domain = domains.NoDomain

NoDomain is the domain of errors that don't originate from a barrier.

func GetDomain

func GetDomain(err error) Domain

GetDomain extracts the domain of the given error, or NoDomain if the error's cause does not have a domain annotation.

func NamedDomain

func NamedDomain(domainName string) Domain

NamedDomain returns an error domain identified by the given string.

func PackageDomain

func PackageDomain() Domain

PackageDomain returns an error domain that represents the package of its caller.

func PackageDomainAtDepth

func PackageDomainAtDepth(depth int) Domain

PackageDomainAtDepth returns an error domain that describes the package at the given call depth.

type DomainOverrideFn

type DomainOverrideFn = func(originalDomain Domain, err error) error

DomainOverrideFn is the type of the callback function passed to EnsureNotInDomain().

type EncodedError

type EncodedError = errbase.EncodedError

EncodedError is the type of an encoded (and protobuf-encodable) error.

func EncodeError

func EncodeError(ctx context.Context, err error) EncodedError

EncodeError encodes an error.

type ErrorDetailer added in v1.2.2

type ErrorDetailer = hintdetail.ErrorDetailer

ErrorDetailer is implemented by types that can provide user-informing detail strings.

type ErrorHinter added in v1.2.2

type ErrorHinter = hintdetail.ErrorHinter

ErrorHinter is implemented by types that can provide user-informing detail strings. This is implemented by withHint here, withIssueLink, assertionFailure and pgerror.Error.

type Formatter added in v1.2.0

type Formatter = errbase.Formatter

A Formatter formats error messages.

NB: Consider implementing SafeFormatter instead. This will ensure that error displays can distinguish bits that are PII-safe.

type IssueLink = issuelink.IssueLink

IssueLink is the payload for a linked issue annotation.

func GetAllIssueLinks(err error) (issues []IssueLink)

GetAllIssueLinks retrieves the linked issue carried by the error or its direct causes.

type LeafDecoder

type LeafDecoder = errbase.LeafDecoder

LeafDecoder is to be provided (via RegisterLeafDecoder above) by additional wrapper types not yet known to this library. A nil return indicates that decoding was not successful.

type LeafEncoder

type LeafEncoder = errbase.LeafEncoder

LeafEncoder is to be provided (via RegisterLeafEncoder above) by additional wrapper types not yet known to this library.

type MultiCauseDecoder added in v1.10.1

type MultiCauseDecoder = errbase.MultiCauseDecoder

MultiCauseDecoder is to be provided (via RegisterMultiCauseDecoder above) by additional multi-cause wrapper types not yet known by the library. A nil return indicates that decoding was not successful.

type MultiCauseEncoder added in v1.10.1

type MultiCauseEncoder = errbase.MultiCauseEncoder

MultiCauseEncoder is to be provided (via RegisterMultiCauseEncoder above) by additional multi-cause wrapper types not yet known to this library. The encoder will automatically extract and encode the causes of this error by calling `Unwrap()` and expecting a slice of errors.

type Printer added in v1.2.0

type Printer = errbase.Printer

A Printer formats error messages.

The most common implementation of Printer is the one provided by package fmt during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message typically provide their own implementations.

type ReportableStackTrace

type ReportableStackTrace = withstack.ReportableStackTrace

ReportableStackTrace aliases the type of the same name in the sentry package. This is used by SendReport().

func GetReportableStackTrace

func GetReportableStackTrace(err error) *ReportableStackTrace

GetReportableStackTrace extracts a stack trace embedded in the given error in the format suitable for Sentry reporting.

This supports:

  • errors generated by github.com/pkg/errors (either generated locally or after transfer through the network),
  • errors generated with WithStack() in this package,
  • any other error that implements a StackTrace() method returning a StackTrace from github.com/pkg/errors.

Note: Sentry wants the oldest call frame first, so the entries are reversed in the result.

type SafeDetailPayload

type SafeDetailPayload = errbase.SafeDetailPayload

SafeDetailPayload captures the safe strings for one level of wrapping.

func GetAllSafeDetails

func GetAllSafeDetails(err error) []SafeDetailPayload

GetAllSafeDetails collects the safe details from the given error object and all its causes. The details are collected from outermost to innermost level of cause.

func GetSafeDetails

func GetSafeDetails(err error) (payload SafeDetailPayload)

GetSafeDetails collects the safe details from the given error object. If it is a wrapper, only the details from the wrapper are returned.

type SafeDetailer

type SafeDetailer = errbase.SafeDetailer

SafeDetailer is an interface that can be implemented by errors that can provide PII-free additional strings suitable for reporting or telemetry.

type SafeFormatter added in v1.7.0

type SafeFormatter = errbase.SafeFormatter

SafeFormatter is implemented by error leaf or wrapper types that want to separate safe and non-safe information when printed out.

When multiple errors are chained (e.g. via errors.Wrap), intermediate layers in the error that do not implement SafeError are considered “unsafe”

type SafeMessager

type SafeMessager = redact.SafeMessager

SafeMessager aliases redact.SafeMessager.

NB: this is obsolete. Use redact.SafeFormatter or errors.SafeFormatter instead.

type TypeKey

type TypeKey = errbase.TypeKey

TypeKey identifies an error for the purpose of looking up decoders. It is equivalent to the "family name" in ErrorTypeMarker.

func GetTypeKey added in v1.2.2

func GetTypeKey(err error) TypeKey

GetTypeKey retrieve the type key for a given error object. This is meant for use in combination with the Register functions.

type Wrapper added in v1.1.0

type Wrapper interface {
	Unwrap() error
}

Wrapper is the type of an error wrapper.

type WrapperDecoder

type WrapperDecoder = errbase.WrapperDecoder

WrapperDecoder is to be provided (via RegisterWrapperDecoder above) by additional wrapper types not yet known to this library. A nil return indicates that decoding was not successful.

type WrapperEncoder

type WrapperEncoder = errbase.WrapperEncoder

WrapperEncoder is to be provided (via RegisterWrapperEncoder above) by additional wrapper types not yet known to this library.

type WrapperEncoderWithMessageType added in v1.10.1

type WrapperEncoderWithMessageType = errbase.WrapperEncoderWithMessageType

WrapperEncoderWithMessageType is to be provided (via RegisterWrapperEncoderWithMessageType) by additional wrapper types not yet known to this library.

Directories

Path Synopsis
Package errutil combines primitives from the library, the Go errors package and github.com/pkg/errors.
Package errutil combines primitives from the library, the Go errors package and github.com/pkg/errors.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL