{"id":13396965,"url":"https://github.com/cockroachdb/errors","last_synced_at":"2025-05-06T02:50:01.397Z","repository":{"id":41241652,"uuid":"190994178","full_name":"cockroachdb/errors","owner":"cockroachdb","description":"Go error library with error portability over the network","archived":false,"fork":false,"pushed_at":"2025-05-05T21:11:12.000Z","size":1381,"stargazers_count":2197,"open_issues_count":18,"forks_count":68,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-05-06T02:49:51.139Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cockroachdb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-09T10:42:19.000Z","updated_at":"2025-05-06T01:08:37.000Z","dependencies_parsed_at":"2025-01-27T22:25:55.686Z","dependency_job_id":"3b420bb1-3b2b-4f17-a198-32e79b3c10c4","html_url":"https://github.com/cockroachdb/errors","commit_stats":{"total_commits":174,"total_committers":26,"mean_commits":"6.6923076923076925","dds":0.5172413793103448,"last_synced_commit":"5b23426aab2f13826e734bad3ffa04568ee03f62"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cockroachdb%2Ferrors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cockroachdb%2Ferrors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cockroachdb%2Ferrors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cockroachdb%2Ferrors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cockroachdb","download_url":"https://codeload.github.com/cockroachdb/errors/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252612452,"owners_count":21776253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T18:01:08.494Z","updated_at":"2025-05-06T02:50:01.391Z","avatar_url":"https://github.com/cockroachdb.png","language":"Go","readme":"# cockroachdb/errors: Go errors with network portability\n\nThis library aims to be used as a drop-in replacement to\n`github.com/pkg/errors` and Go's standard `errors` package.  It also\nprovides *network portability* of error objects, in ways suitable for\ndistributed systems with mixed-version software compatibility.\n\nIt also provides native and comprehensive support for [PII](https://en.wikipedia.org/wiki/Personal_data)-free details\nand an opt-in [Sentry.io](https://sentry.io/) reporting mechanism that\nautomatically formats error details and strips them of PII.\n\nSee also [the design RFC](https://github.com/cockroachdb/cockroach/blob/master/docs/RFCS/20190318_error_handling.md).\n\n![Build Status](https://github.com/cockroachdb/errors/actions/workflows/ci.yaml/badge.svg?branch=master)\n[![Go Reference](https://pkg.go.dev/badge/github.com/cockroachdb/errors.svg)](https://pkg.go.dev/github.com/cockroachdb/errors)\n\nTable of contents:\n\n- [Features](#Features)\n- [How to use](#How-to-use)\n- [What comes out of an error?](#What-comes-out-of-an-error)\n- [Available error leaves](#Available-error-leaves)\n- [Available wrapper constructors](#Available-wrapper-constructors)\n- [Providing PII-free details](#Providing-PII-free-details)\n- [Building your own error types](#Building-your-own-error-types)\n- [Error composition (summary)](#Error-composition-summary)\n- [API (not constructing error objects)](#API-not-constructing-error-objects)\n\n## Features\n\n| Feature                                                                                               | Go's \u003c1.13 `errors` | `github.com/pkg/errors` | Go 1.13 `errors`/`xerrors` | `cockroachdb/errors` |\n|-------------------------------------------------------------------------------------------------------|---------------------|-------------------------|----------------------------|----------------------|\n| error constructors (`New`, `Errorf` etc)                                                              | ✔                   | ✔                       | ✔                          | ✔                    |\n| error causes (`Cause` / `Unwrap`)                                                                     |                     | ✔                       | ✔                          | ✔                    |\n| cause barriers (`Opaque` / `Handled`)                                                                 |                     |                         | ✔                          | ✔                    |\n| `errors.As()`, `errors.Is()`                                                                          |                     |                         | ✔                          | ✔                    |\n| automatic error wrap when format ends with `: %w`                                                     |                     |                         | ✔                          | ✔                    |\n| standard wrappers with efficient stack trace capture                                                  |                     | ✔                       |                            | ✔                    |\n| **transparent protobuf encode/decode with forward compatibility**                                     |                     |                         |                            | ✔                    |\n| **`errors.Is()` recognizes errors across the network**                                                |                     |                         |                            | ✔                    |\n| **comprehensive support for PII-free reportable strings**                                             |                     |                         |                            | ✔                    |\n| support for both `Cause()` and `Unwrap()` [go#31778](https://github.com/golang/go/issues/31778)       |                     |                         |                            | ✔                    |\n| standard error reports to Sentry.io                                                                   |                     |                         |                            | ✔                    |\n| wrappers to denote assertion failures                                                                 |                     |                         |                            | ✔                    |\n| wrappers with issue tracker references                                                                |                     |                         |                            | ✔                    |\n| wrappers for user-facing hints and details                                                            |                     |                         |                            | ✔                    |\n| wrappers to attach secondary causes                                                                   |                     |                         |                            | ✔                    |\n| wrappers to attach [`logtags`](https://github.com/cockroachdb/logtags) details from `context.Context` |                     |                         |                            | ✔                    |\n| `errors.FormatError()`, `Formatter`, `Printer`                                                        |                     |                         | (under construction)       | ✔                    |\n| `errors.SafeFormatError()`, `SafeFormatter`                                                           |                     |                         |                            | ✔                    |\n| wrapper-aware `IsPermission()`, `IsTimeout()`, `IsExist()`, `IsNotExist()`                            |                     |                         |                            | ✔                    |\n\n\"Forward compatibility\" above refers to the ability of this library to\nrecognize and properly handle network communication of error types it\ndoes not know about, for example when a more recent version of a\nsoftware package sends a new error object to another system running an\nolder version of the package.\n\n## How to use\n\n- construct errors with `errors.New()`, etc as usual, but also see the other [error leaf constructors](#Available-error-leaves) below.\n- wrap errors with `errors.Wrap()` as usual, but also see the [other wrappers](#Available-wrapper-constructors) below.\n- test error identity with `errors.Is()` as usual.\n  **Unique in this library**: this works even if the error has traversed the network!\n  Also, `errors.IsAny()` to recognize two or more reference errors.\n- replace uses of `os.IsPermission()`, `os.IsTimeout()`, `os.IsExist()` and `os.IsNotExist()` by their analog in sub-package `oserror` so\n  that they can peek through layers of wrapping.\n- access error causes with `errors.UnwrapOnce()` / `errors.UnwrapAll()` (note: `errors.Cause()` and `errors.Unwrap()` also provided for compatibility with other error packages).\n- encode/decode errors to protobuf with `errors.EncodeError()` / `errors.DecodeError()`.\n- extract **PII-free safe details** with `errors.GetSafeDetails()`.\n- extract human-facing hints and details with `errors.GetAllHints()`/`errors.GetAllDetails()` or `errors.FlattenHints()`/`errors.FlattenDetails()`.\n- produce detailed Sentry.io reports with `errors.BuildSentryReport()` / `errors.ReportError()`.\n- implement your own error leaf types and wrapper types:\n  - implement the `error` and `errors.Wrapper` interfaces as usual.\n  - register encode/decode functions: call `errors.Register{Leaf,Wrapper}{Encoder,Decoder}()` in a `init()` function in your package.\n  - implement `Format()` that redirects to `errors.FormatError()`.\n  - see the section [Building your own error types](#Building-your-own-error-types) below.\n\n## What comes out of an error?\n\n| Error detail                                                    | `Error()` and format `%s`/`%q`/`%v` | format `%+v` | `GetSafeDetails()`            | Sentry report via `ReportError()` |\n|-----------------------------------------------------------------|-------------------------------------|--------------|-------------------------------|-----------------------------------|\n| main message, eg `New()`                                        | visible                             | visible      | yes (CHANGED IN v1.6)         | full (CHANGED IN v1.6)            |\n| wrap prefix, eg `WithMessage()`                                 | visible (as prefix)                 | visible      | yes (CHANGED IN v1.6)         | full (CHANGED IN v1.6)            |\n| stack trace, eg `WithStack()`                                   | not visible                         | simplified   | yes                           | full                              |\n| hint , eg `WithHint()`                                          | not visible                         | visible      | no                            | type only                         |\n| detail, eg `WithDetail()`                                       | not visible                         | visible      | no                            | type only                         |\n| assertion failure annotation, eg `WithAssertionFailure()`       | not visible                         | visible      | no                            | type only                         |\n| issue links, eg `WithIssueLink()`, `UnimplementedError()`       | not visible                         | visible      | yes                           | full                              |\n| safe details, eg `WithSafeDetails()`                            | not visible                         | visible      | yes                           | full                              |\n| telemetry keys, eg. `WithTelemetryKey()`                        | not visible                         | visible      | yes                           | full                              |\n| secondary errors, eg. `WithSecondaryError()`, `CombineErrors()` | not visible                         | visible      | redacted, recursively         | redacted, recursively             |\n| barrier origins, eg. `Handled()`                                | not visible                         | visible      | redacted, recursively         | redacted, recursively             |\n| error domain, eg. `WithDomain()`                                | not visible                         | visible      | yes                           | full                              |\n| context tags, eg. `WithContextTags()`                           | not visible                         | visible      | keys visible, values redacted | keys visible, values redacted     |\n\n## Available error leaves\n\nAn error *leaf* is an object that implements the `error` interface,\nbut does not refer to another error via a `Unwrap()` or `Cause()`\nmethod.\n\n- `New(string) error`, `Newf(string, ...interface{}) error`, `Errorf(string, ...interface{}) error`: leaf errors with message\n  - **when to use: common error cases.**\n  - what it does: also captures the stack trace at point of call and redacts the provided message for safe reporting.\n  - how to access the detail: `Error()`, regular Go formatting. **Details in Sentry report.**\n  - see also: Section [Error composition](#Error-composition-summary) below. `errors.NewWithDepth()` variants to customize at which call depth the stack trace is captured.\n\n- `AssertionFailedf(string, ...interface{}) error`, `NewAssertionFailureWithWrappedErrf(error, string, ...interface{}) error`: signals an assertion failure / programming error.\n  - **when to use: when an invariant is violated; when an unreachable code path is reached.**\n  - 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.\n  - how to access the detail: `IsAssertionFailure()`/`HasAssertionFailure()`, format with `%+v`, Safe details included in Sentry reports.\n  - see also: Section [Error composition](#Error-composition-summary) below. `errors.AssertionFailedWithDepthf()` variant to customize at which call depth the stack trace is captured.\n\n- `Handled(error) error`, `Opaque(error) error`, `HandledWithMessage(error, string) error`: captures an error cause but make it invisible to `Unwrap()` / `Is()`.\n  - **when to use: when a new error occurs while handling an error, and the original error must be \"hidden\".**\n  - what it does: captures the cause in a hidden field. The error message is preserved unless the `...WithMessage()` variant is used.\n  - how to access the detail: format with `%+v`, redacted details reported in Sentry reports.\n\n- `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.\n  - **when to use: to inform (human) users that some feature is not implemented yet and refer them to some external resource.**\n  - what it does: captures the message, URL and detail in a wrapper. The URL and detail are considered safe for reporting.\n  - how to access the detail: `errors.GetAllHints()`, `errors.FlattenHints()`, format with `%+v`, URL and detail included in Sentry report (not the message).\n  - see also: `errors.WithIssueLink()` below for errors that are not specifically about unimplemented features.\n\n## Available wrapper constructors\n\nAn error *wrapper* is an object that implements the `error` interface,\nand also refers to another error via an `Unwrap()` (preferred) and/or\n`Cause()` method.\n\nAll wrapper constructors can be applied safely to a `nil` `error`:\nthey behave as no-ops in this case:\n\n```go\n// The following:\n// if err := foo(); err != nil {\n//    return errors.Wrap(err, \"foo\")\n// }\n// return nil\n//\n// is not needed. Instead, you can use this:\nreturn errors.Wrap(foo(), \"foo\")\n```\n\n- `Wrap(error, string) error`, `Wrapf(error, string, ...interface{}) error`:\n  - **when to use: on error return paths.**\n  - what it does: combines `WithMessage()`, `WithStack()`, `WithSafeDetails()`.\n  - how to access the details: `Error()`, regular Go formatting. **Details in Sentry report.**\n  - see also: Section [Error composition](#Error-composition-summary) below. `WrapWithDepth()` variants to customize at which depth the stack trace is captured.\n\n- `WithSecondaryError(error, error) error`: annotate an error with a secondary error.\n  - **when to use: when an additional error occurs in the code that is handling a primary error.** Consider using `errors.CombineErrors()` instead (see below).\n  - what it does: it captures the secondary error but hides it from `errors.Is()`.\n  - how to access the detail: format with `%+v`, redacted recursively in Sentry reports.\n  - see also: `errors.CombineErrors()`\n\n- `CombineErrors(error, error) error`: combines two errors into one.\n  - **when to use: when two operations occur concurrently and either can return an error, and only one final error must be returned.**\n  - what it does: returns either of its arguments if the other is `nil`, otherwise calls `WithSecondaryError()`.\n  - how to access the detail: see `WithSecondaryError()` above.\n\n- `Mark(error, error) error`: gives the identity of one error to another error.\n  - **when to use: when a caller expects to recognize a sentinel error with `errors.Is()` but the callee provides a diversity of error messages.**\n  - what it does: it overrides the \"error mark\" used internally by `errors.Is()`.\n  - how to access the detail: format with `%+v`, Sentry reports.\n\n- `WithStack(error) error`: annotate with stack trace\n  - **when to use:** usually not needed, use `errors.Wrap()`/`errors.Wrapf()` instead.\n\n    **Special cases:**\n\n    - when returning a sentinel, for example:\n\n      ```go\n      var myErr = errors.New(\"foo\")\n\n      func myFunc() error {\n        if ... {\n           return errors.WithStack(myErr)\n        }\n      }\n      ```\n\n    - on error return paths, when not trivial but also not warranting a wrap. For example:\n\n      ```go\n      err := foo()\n      if err != nil {\n        doSomething()\n        if !somecond {\n           return errors.WithStack(err)\n        }\n      }\n        ```\n\n  - what it does: captures (efficiently) a stack trace.\n  - how to access the details: format with `%+v`, `errors.GetSafeDetails()`, Sentry reports. The stack trace is considered safe for reporting.\n  - see also: `WithStackDepth()` to customize the call depth at which the stack trace is captured.\n\n- `WithSafeDetails(error, string, ...interface{}) error`: safe details for reporting.\n  - when to use: probably never. Use `errors.Wrap()`/`errors.Wrapf()` instead.\n  - what it does: saves some strings for safe reporting.\n  - how to access the detail: format with `%+v`, `errors.GetSafeDetails()`, Sentry report.\n\n- `WithMessage(error, string) error`, `WithMessagef(error, string, ...interface{}) error`: message prefix.\n  - when to use: probably never. Use `errors.Wrap()`/`errors.Wrapf()` instead.\n  - what it does: adds a message prefix.\n  - how to access the detail: `Error()`, regular Go formatting, Sentry Report.\n\n- `WithDetail(error, string) error`, `WithDetailf(error, string, ...interface{}) error`, user-facing detail with contextual information.\n  - **when to use: need to embark a message string to output when the error is presented to a developer.**\n  - what it does: captures detail strings.\n  - how to access the detail: `errors.GetAllDetails()`, `errors.FlattenDetails()` (all details are preserved), format with `%+v`. Not included in Sentry reports.\n\n- `WithHint(error, string) error`, `WithHintf(error, string, ...interface{}) error`: user-facing detail with suggestion for action to take.\n  - **when to use: need to embark a message string to output when the error is presented to an end user.**\n  - what it does: captures hint strings.\n  - how to access the detail: `errors.GetAllHints()`, `errors.FlattenHints()` (hints are de-duplicated), format with `%+v`. Not included in Sentry reports.\n\n- `WithIssueLink(error, IssueLink) error`: annotate an error with an URL and arbitrary string.\n  - **when to use: to refer (human) users to some external resources.**\n  - what it does: captures the URL and detail in a wrapper. Both are considered safe for reporting.\n  - how to access the detail: `errors.GetAllHints()`, `errors.FlattenHints()`,  `errors.GetSafeDetails()`, format with `%+v`, Sentry report.\n  - see also: `errors.UnimplementedError()` to construct leaves (see previous section).\n\n- `WithTelemetry(error, string) error`: annotate an error with a key suitable for telemetry.\n  - **when to use: to gather strings during error handling, for capture in the telemetry sub-system of a server package.**\n  - what it does: captures the string. The telemetry key is considered safe for reporting.\n  - how to access the detail: `errors.GetTelemetryKeys()`,  `errors.GetSafeDetails()`, format with `%+v`, Sentry report.\n\n- `WithDomain(error, Domain) error`, `HandledInDomain(error, Domain) error`, `HandledInDomainWithMessage(error, Domain, string) error` **(experimental)**: annotate an error with an origin package.\n  - **when to use: at package boundaries.**\n  - what it does: captures the identity of the error domain. Can be asserted with `errors.EnsureNotInDomain()`, `errors.NotInDomain()`.\n  - how to access the detail: format with `%+v`, Sentry report.\n\n- `WithAssertionFailure(error) error`: annotate an error as being an assertion failure.\n  - when to use: probably never. Use `errors.AssertionFailedf()` and variants.\n  - what it does: wraps the error with a special type. Triggers an auto-generated hint.\n  - how to access the detail: `IsAssertionFailure()`/`HasAssertionFailure()`, `errors.GetAllHints()`, `errors.FlattenHints()`, format with `%+v`, Sentry report.\n\n- `WithContextTags(error, context.Context) error`: annotate an error with the k/v pairs attached to a `context.Context` instance with the [`logtags`](https://github.com/cockroachdb/logtags) package.\n  - **when to use: when capturing/producing an error and a `context.Context` is available.**\n  - what it does: it captures the `logtags.Buffer` object in the wrapper.\n  - how to access the detail: `errors.GetContextTags()`, format with `%+v`, Sentry reports.\n\n## Providing PII-free details\n\nThe library support PII-free strings essentially as follows:\n\n- by default, many strings included in an error object are considered\n  to be PII-unsafe, and are stripped out when building a Sentry\n  report.\n- some fields in the library are assumed to be PII-safe by default.\n- you can opt additional strings in to Sentry reports.\n\nThe following strings from this library are considered to be PII-free,\nand thus included in Sentry reports automatically:\n\n- the *type* of error objects,\n- stack traces (containing only file paths, line numbers, function names - arguments are not included),\n- issue tracker links (including URL and detail field),\n- telemetry keys,\n- error domains,\n- context tag keys,\n- the `format string` argument of `Newf`, `AssertionFailedf`, etc (the constructors ending with `...f()`),\n- the *type* of the additional arguments passed to the `...f()` constructors,\n- the *value of specific argument types* passed to the `...f()` constructors, when known to be PII-safe.\n  For details of which arguments are considered PII-free, see the [`redact` package](https://github.com/cockroachdb/redact).\n\nIt is possible to opt additional in to Sentry reporting, using either of the following methods:\n\n- implement the `errors.SafeDetailer` interface, providing the\n  `SafeDetails() []string` method on your error type.\n\n- enclose additional arguments passed to the `...f()` constructors with `errors.Safe()`. For example:\n  `err := errors.Newf(\"my code: %d\", errors.Safe(123))`\n  — in this example, the value 123 will be included when a Sentry report is constructed.\n  - it also makes it available via `errors.GetSafeDetails()`/`GetAllSafeDetails()`.\n  - the value 123 is also part of the main error message returned by `Error()`.\n\n- attach additional arbitrary strings with `errors.WithSafeDetails(error, string, ...interface{}) error` and\n  also use `errors.Safe()`.\n  For example: `err = errors.WithSafeDetails(err, \"additional data: %s\", errors.Safe(\"hello\"))`.\n  - in this example, the string \"hello\" will be included in Sentry reports.\n  - however, it is not part of the main error message returned by `Error()`.\n\nFor more details on how Sentry reports are built, see the [`report`](report) sub-package.\n\n## Building your own error types\n\nYou can create an error type as usual in Go: implement the `error`\ninterface, and, if your type is also a wrapper, the `errors.Wrapper`\ninterface (an `Unwrap()` method). You may also want to implement the\n`Cause()` method for backward compatibility with\n`github.com/pkg/errors`, if your project also uses that.\n\nIf your error type is a wrapper, you should implement a `Format()`\nmethod that redirects to `errors.FormatError()`, otherwise `%+v` will\nnot work. Additionally, if your type has a payload not otherwise\nvisible via `Error()`, you may want to implement\n`errors.SafeFormatter`. See [making `%+v` work with your\ntype](#Making-v-work-with-your-type) below for details.\n\nFinally, you may want your new error type to be portable across\nthe network.\n\nIf your error type is a leaf, and already implements `proto.Message`\n(from [gogoproto](https://github.com/gogo/protobuf)), you are all set\nand the errors library will use that automatically. If you do not or\ncannot implement `proto.Message`, or your error type is a wrapper,\nread on.\n\nAt a minimum, you will need a *decoder function*: while\n`cockroachdb/errors` already does a bunch of encoding/decoding work on\nnew types automatically, the one thing it really cannot do on its own\nis instantiate a Go object using your new type.\n\nHere is the simplest decode function for a new leaf error type and a\nnew wrapper type:\n\n```go\n// note: we use the gogoproto `proto` sub-package.\nfunc yourDecode(_ string, _ []string, _ proto.Message) error {\n   return \u0026yourType{}\n}\n\nfunc init() {\n   errors.RegisterLeafEncoder((*yourType)(nil), yourDecodeFunc)\n}\n\nfunc yourDecodeWrapper(cause error, _ string, _ []string, _ proto.Message) error {\n   // Note: the library already takes care of encoding/decoding the cause.\n   return \u0026yourWrapperType{cause: cause}\n}\n\nfunc init() {\n   errors.RegisterWrapperDecoder((*yourWrapperType)(nil), yourDecodeWrapper)\n}\n```\n\nIn the case where your type does not have any other field (empty\nstruct for leafs, just a cause for wrappers), this is all you have to\ndo.\n\n(See the type `withAssertionFailure` in\n[`assert/assert.go`](assert/assert.go) for an example of this simple\ncase.)\n\nIf your type does have additional fields, you *may* still not need a\ncustom encoder.  This is because the library automatically\nencodes/decodes the main error message and any safe strings that your\nerror types makes available via the `errors.SafeDetailer` interface\n(the `SafeDetails()` method).\n\nSay, for example, you have the following leaf type:\n\n```go\ntype myLeaf struct {\n   code int\n}\n\nfunc (m *myLeaf) Error() string { return fmt.Sprintf(\"my error: %d\" + m.code }\n```\n\nIn that case, the library will automatically encode the result of\ncalling `Error()`. This string will then be passed back to your\ndecoder function as the first argument. This makes it possible\nto decode the `code` field exactly:\n\n```go\nfunc myLeafDecoder(msg string, _ []string, _ proto.Message) error {\n\tcodeS := strings.TrimPrefix(msg, \"my error: \")\n\tcode, _ := strconv.Atoi(codeS)\n\t// Note: error handling for strconv is omitted here to simplify\n\t// the explanation. If your decoder function should fail, simply\n\t// return a `nil` error object (not another unrelated error!).\n\treturn \u0026myLeaf{code: code}\n}\n```\n\nLikewise, if your fields are PII-free, they are safe to expose via the\n`errors.SafeDetailer` interface. Those strings also get encoded\nautomatically, and get passed to the decoder function as the second\nargument.\n\nFor example, say you have the following leaf type:\n\n```go\ntype myLeaf struct {\n   // both fields are PII-free.\n   code int\n   tag string\n}\n\nfunc (m *myLeaf) Error() string { ... }\n```\n\nThen you can expose the fields as safe details as follows:\n\n```go\nfunc (m *myLeaf) SafeDetails() []string {\n  return []string{fmt.Sprintf(\"%d\", m.code), m.tag}\n}\n```\n\n(If the data is PII-free, then it is good to do this in any case: it\nenables any network system that receives an error of your type, but\ndoes not know about it, to still produce useful Sentry reports.)\n\nOnce you have this, the decode function receives the strings and you\ncan use them to re-construct the error:\n\n```go\nfunc myLeafDecoder(_ string, details []string, _ proto.Message) error {\n    // Note: you may want to test the length of the details slice\n\t// is correct.\n    code, _ := strconv.Atoi(details[0])\n    tag := details[1]\n\treturn \u0026myLeaf{code: code, tag: tag}\n}\n```\n\n(For an example, see the `withTelemetry` type in [`telemetry/with_telemetry.go`](telemetry/with_telemetry.go).)\n\n__The only case where you need a custom encoder is when your error\ntype contains some fields that are not reflected in the error message\n(so you can't extract them back from there), and are not PII-free and\nthus cannot be reported as \"safe details\".__\n\nTo take inspiration from examples, see the following types in the\nlibrary that need a custom encoder:\n\n- Hints/details in [`hintdetail/with_hint.go`](hintdetail/with_hint.go) and [`hintdetail/with_detail.go`](hintdetail/with_detail.go).\n- Secondary error wrappers in [`secondary/with_secondary.go`](secondary/with_secondary.go).\n- Marker error wrappers at the end of [`markers/markers.go`](markers/markers.go).\n\n### Making `%+v` work with your type\n\nIn short:\n\n- When in doubt, you should always implement the `fmt.Formatter`\n  interface (`Format(fmt.State, rune)`) on your custom error types,\n  exactly as follows:\n\n  ```go\n  func (e *yourType) Format(s *fmt.State, verb rune) { errors.FormatError(e, s, verb) }\n  ```\n\n  (If you do not provide this redirection for your own custom wrapper\n  type, this will disable the recursive application of the `%+v` flag\n  to the causes chained from your wrapper.)\n\n- You may optionally implement the `errors.SafeFormatter` interface:\n  `SafeFormatError(p errors.Printer) (next error)`.  This is optional, but\n  should be done when some details are not included by `Error()` and\n  should be emitted upon `%+v`.\n\nThe example `withHTTPCode` wrapper [included in the source tree](exthttp/ext_http.go)\nachieves this as follows:\n\n```go\n// Format() implements fmt.Formatter, is required until Go knows about FormatError.\nfunc (w *withHTTPCode) Format(s fmt.State, verb rune) { errors.FormatError(w, s, verb) }\n\n// FormatError() formats the error.\nfunc (w *withHTTPCode) SafeFormatError(p errors.Printer) (next error) {\n\t// Note: no need to print out the cause here!\n\t// FormatError() knows how to do this automatically.\n\tif p.Detail() {\n\t\tp.Printf(\"http code: %d\", errors.Safe(w.code))\n\t}\n\treturn w.cause\n}\n\n```\n\nTechnical details follow:\n\n- The errors library follows [the Go 2\nproposal](https://go.googlesource.com/proposal/+/master/design/29934-error-values.md).\n\n- At some point in the future, Go's standard `fmt` library will learn\n  [how to recognize error wrappers, and how to use the `errors.Formatter`\n  interface automatically](https://github.com/golang/go/issues/29934).  Until\n  then, you must ensure that you also implement a `Format()` method\n  (from `fmt.Formatter`) that redirects to `errors.FormatError`.\n\n  Note: you may implement `fmt.Formatter` (`Format()` method) in this\n  way without implementing `errors.Formatter` (a `FormatError()`\n  method). In that case, `errors.FormatError` will use a separate code\n  path that does \"the right thing\", even for wrappers.\n\n- The library provides an implementation of `errors.FormatError()`,\n  modeled after the same function in Go 2. This is responsible for\n  printing out error details, and knows how to present a chain of\n  causes in a semi-structured format upon formatting with `%+v`.\n\n### Ensuring `errors.Is` works when errors/packages are renamed\n\nIf a Go package containing a custom error type is renamed, or the\nerror type itself is renamed, and errors of this type are transported\nover the network, then another system with a different code layout\n(e.g. running a different version of the software) may not be able to\nrecognize the error any more via `errors.Is`.\n\nTo ensure that network portability continues to work across multiple\nsoftware versions, in the case error types get renamed or Go packages\nget moved / renamed / etc, the server code must call\n`errors.RegisterTypeMigration()` from e.g. an `init()` function.\n\nExample use:\n\n```go\n previousPath := \"github.com/old/path/to/error/package\"\n previousTypeName := \"oldpackage.oldErrorName\"\n newErrorInstance := \u0026newTypeName{...}\n errors.RegisterTypeMigration(previousPath, previousTypeName, newErrorInstance)\n```\n\n## Error composition (summary)\n\n| Constructor                        | Composes                                                                          |\n|------------------------------------|-----------------------------------------------------------------------------------|\n| `New`                              | `NewWithDepth` (see below)                                                        |\n| `Errorf`                           | = `Newf`                                                                          |\n| `Newf`                             | `NewWithDepthf` (see below)                                                       |\n| `WithMessage`                      | custom wrapper with message prefix and knowledge of safe strings                  |\n| `Wrap`                             | `WrapWithDepth` (see below)                                                       |\n| `Wrapf`                            | `WrapWithDepthf` (see below)                                                      |\n| `AssertionFailed`                  | `AssertionFailedWithDepthf` (see below)                                           |\n| `NewWithDepth`                     | custom leaf with knowledge of safe strings + `WithStackDepth` (see below)         |\n| `NewWithDepthf`                    | custom leaf with knowledge of safe strings + `WithSafeDetails` + `WithStackDepth` |\n| `WithMessagef`                     | custom wrapper with message prefix and knowledge of safe strings                  |\n| `WrapWithDepth`                    | `WithMessage` + `WithStackDepth`                                                  |\n| `WrapWithDepthf`                   | `WithMessagef` + `WithStackDepth`                                                 |\n| `AssertionFailedWithDepthf`        | `NewWithDepthf` + `WithAssertionFailure`                                          |\n| `NewAssertionErrorWithWrappedErrf` | `HandledWithMessagef` (barrier) + `WrapWithDepthf` +  `WithAssertionFailure`      |\n| `Join`                             | `JoinWithDepth` (see below)                                                       |\n| `JoinWithDepth`                    | multi-cause wrapper + `WithStackDepth`                                            |\n## API (not constructing error objects)\n\nThe following is a summary of the non-constructor API functions, grouped by category.\nDetailed documentation can be found at: https://pkg.go.dev/github.com/cockroachdb/errors\n\n```go\n// Access causes.\nfunc UnwrapAll(err error) error\nfunc UnwrapOnce(err error) error\nfunc Cause(err error) error // compatibility\nfunc Unwrap(err error) error // compatibility\ntype Wrapper interface { ... } // compatibility\n\n// Error formatting.\ntype Formatter interface { ... } // compatibility, not recommended\ntype SafeFormatter interface { ... }\ntype Printer interface { ... }\nfunc FormatError(err error, s fmt.State, verb rune)\nfunc Formattable(err error) fmt.Formatter\n\n// Identify errors.\nfunc Is(err, reference error) bool\nfunc IsAny(err error, references ...error) bool\nfunc If(err error, pred func(err error) (interface{}, bool)) (interface{}, bool)\nfunc As(err error, target interface{}) bool\n\n// Encode/decode errors.\ntype EncodedError // this is protobuf-encodable\nfunc EncodeError(ctx context.Context, err error) EncodedError\nfunc DecodeError(ctx context.Context, enc EncodedError) error\n\n// Register encode/decode functions for custom/new error types.\nfunc RegisterLeafDecoder(typeName TypeKey, decoder LeafDecoder)\nfunc RegisterLeafEncoder(typeName TypeKey, encoder LeafEncoder)\nfunc RegisterWrapperDecoder(typeName TypeKey, decoder WrapperDecoder)\nfunc RegisterWrapperEncoder(typeName TypeKey, encoder WrapperEncoder)\nfunc RegisterWrapperEncoderWithMessageOverride (typeName TypeKey, encoder WrapperEncoderWithMessageOverride)\nfunc RegisterMultiCauseEncoder(theType TypeKey, encoder MultiCauseEncoder)\nfunc RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder)\ntype LeafEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message)\ntype LeafDecoder = func(ctx context.Context, msg string, safeDetails []string, payload proto.Message) error\ntype WrapperEncoder = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message)\ntype WrapperEncoderWithMessageOverride = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message, overrideError bool)\ntype WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, safeDetails []string, payload proto.Message) error\ntype MultiCauseEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message)\ntype MultiCauseDecoder = func(ctx context.Context, causes []error, msgPrefix string, safeDetails []string, payload proto.Message) error\n\n// Registering package renames for custom error types.\nfunc RegisterTypeMigration(previousPkgPath, previousTypeName string, newType error)\n\n// Sentry reports.\nfunc BuildSentryReport(err error) (*sentry.Event, map[string]interface{})\nfunc ReportError(err error) (string)\n\n// Stack trace captures.\nfunc GetOneLineSource(err error) (file string, line int, fn string, ok bool)\ntype ReportableStackTrace = sentry.StackTrace\nfunc GetReportableStackTrace(err error) *ReportableStackTrace\n\n// Safe (PII-free) details.\ntype SafeDetailPayload struct { ... }\nfunc GetAllSafeDetails(err error) []SafeDetailPayload\nfunc GetSafeDetails(err error) (payload SafeDetailPayload)\n\n// Obsolete APIs.\ntype SafeMessager interface { ... }\nfunc Redact(r interface{}) string\n\n// Aliases redact.Safe.\nfunc Safe(v interface{}) SafeMessager\n\n// Assertion failures.\nfunc HasAssertionFailure(err error) bool\nfunc IsAssertionFailure(err error) bool\n\n// User-facing details and hints.\nfunc GetAllDetails(err error) []string\nfunc FlattenDetails(err error) string\nfunc GetAllHints(err error) []string\nfunc FlattenHints(err error) string\n\n// Issue links / URL wrappers.\nfunc HasIssueLink(err error) bool\nfunc IsIssueLink(err error) bool\nfunc GetAllIssueLinks(err error) (issues []IssueLink)\n\n// Unimplemented errors.\nfunc HasUnimplementedError(err error) bool\nfunc IsUnimplementedError(err error) bool\n\n// Telemetry keys.\nfunc GetTelemetryKeys(err error) []string\n\n// Domain errors.\ntype Domain\nconst NoDomain Domain\nfunc GetDomain(err error) Domain\nfunc NamedDomain(domainName string) Domain\nfunc PackageDomain() Domain\nfunc PackageDomainAtDepth(depth int) Domain\nfunc EnsureNotInDomain(err error, constructor DomainOverrideFn, forbiddenDomains ...Domain) error\nfunc NotInDomain(err error, doms ...Domain) bool\n\n// Context tags.\nfunc GetContextTags(err error) []*logtags.Buffer\n```\n","funding_links":[],"categories":["Go","开源类库","Error Handling","Open source library","错误处理"],"sub_categories":["错误处理","Search and Analytic Databases","Error Handling","检索及分析资料库","Advanced Console UIs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcockroachdb%2Ferrors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcockroachdb%2Ferrors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcockroachdb%2Ferrors/lists"}