{"id":29569229,"url":"https://github.com/roserocket/xerrs","last_synced_at":"2025-10-13T18:43:14.023Z","repository":{"id":57480999,"uuid":"147353661","full_name":"RoseRocket/xerrs","owner":"RoseRocket","description":"Extended Errors (or simply xerrs) for GoLang","archived":false,"fork":false,"pushed_at":"2020-09-03T18:56:15.000Z","size":109,"stargazers_count":64,"open_issues_count":0,"forks_count":4,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-08-13T21:15:42.467Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RoseRocket.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}},"created_at":"2018-09-04T13:50:01.000Z","updated_at":"2025-07-10T12:49:59.000Z","dependencies_parsed_at":"2022-09-26T17:41:26.608Z","dependency_job_id":null,"html_url":"https://github.com/RoseRocket/xerrs","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/RoseRocket/xerrs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoseRocket%2Fxerrs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoseRocket%2Fxerrs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoseRocket%2Fxerrs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoseRocket%2Fxerrs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RoseRocket","download_url":"https://codeload.github.com/RoseRocket/xerrs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoseRocket%2Fxerrs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279016600,"owners_count":26085852,"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","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-07-19T01:40:08.445Z","updated_at":"2025-10-13T18:43:14.016Z","avatar_url":"https://github.com/RoseRocket.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xerrs [![Build Status](https://travis-ci.org/RoseRocket/xerrs.svg?branch=master)](https://travis-ci.org/RoseRocket/xerrs)\n\nExtended Errors for Go\n\n## What? Why?\n\nIt is extremely important to be able to effectively debug problems in production. However, depending\non the simplicty of your language's error handling, managing errors and debugging can become tedious\nand difficult. For instance, GoLang provides a basic error which contains a simple value - but it\nlacks verbose information about the cause of the error or the state of the stack at error-time.\n\nxerrs uses original GoLang built-in error types but stores extra data.\n\nThese are the extra extended features which could be useful for debugging a big project:\n\n1. **Cause** - the original error which happened in the system. This is the original error which you\n   want to preserve\n2. **Mask** - a mask error. It might be used whenever you want to mask some errors happening on\n   production with a more generic error. Mask is very useful if you want to prevent original error\n   return back to the client. Calling Error() will always return Mask if set.\n3. **Stack** - a detailed snapshot of the execution stack at error-time. Helpful for debugging.\n4. **Data** - a map which could be used to store custom data associated with an error.\n5. **Wrap** and **Wrapf** can be used to create an annotated error chain, but\n   take a lower precedence than **Mask**.\n\n## Quick Usage\n\n### Basics\n\n```go\nimport \"github.com/roserocket/xerrs\"\n\n//....\n\nif data, err := MyFunc(); err != nil {\n    err := xerrs.Extend(err) // extend error\n\n    //....\n\n    // Details returns cause error, mask if specified, and the stack (accepting the maximum stack height as parameter)\n    // In this example only 5 last stack function calls will be printed out\n    fmt.Println(xerrs.Details(err, 5))\n\n    //....\n}\n```\n\n### Deferred logging + masking example\n\n```go\nfunc DoSomething(w http.ResponseWriter, r *http.Request) {\n    var err error\n\n    const maxCallstack = 5 // only 5 last stack function calls will be printed out\n\n    defer func() {\n        // Details returns cause error, mask if specified, and the stack (accepting the maximum stack height as parameter)\n        // In this example only 5 calls in the stack will be printed out\n        fmt.Println(xerrs.Details(err, maxCallstack))\n    }()\n\n    var someModel Model\n    if err = ReadJSONFromReader(r, \u0026someModel); err != nil {\n        err = xerrs.Extend(err)\n        DoSomethingWithError(w, err.Error()) // Calling Error() without setting a mask will return the original error.\n        return\n    }\n\n    if _, err = DBCreateMyModel(\u0026someModel); err != nil {\n        err = xerrs.Mask(err, errors.New(\"We are experiencing technical difficulties\"))\n        DoSomethingWithError(w, err.Error()) // Error() will return the masked error in this case.\n        return\n    }\n\n    OutputDataToClient(w, \u0026someModel)\n}\n```\n\n### Custom data in error\n\n```go\nfunc DoSomething(w http.ResponseWriter, r *http.Request) {\n    var err error\n\n    //......\n\n    if err = ReadJSONFromReader(r, someModel); err != nil {\n        err = xerrs.Extend(err)\n\n        xerrs.SetData(err, \"some_key\", \"VALUE\") // set custom error value\n    }\n\n    //......\n\n    fmt.Println(xerrs.Details(err))\n    fmt.Println(xerrs.GetData(err, \"some_key\")) // print custom error value\n\n    //......\n}\n```\n\n### Compare errors\n\n```go\nfunc VeryComplexLongFunction(arg1, arg2) error {\n    var err error\n    badErr := errors.New(\"EPIC FAIL\")\n\n    //......\n\n    // convert error to an extended one and use it to for debugging purposes\n    err = xerrs.Extend(err)\n\n    //......\n\n    if xerrs.IsEqual(err, badErr) {\n        // errors are equal. We need to do something here\n    }\n\n    //......\n}\n```\n\n### Wrapped errors\n\n#### Basic wrapping\n\n```go\nfunc main() {\n\tif err := a(); err != nil {\n\t\tlog.Fatalln(err)\n\t}\n}\n\nfunc a() error {\n\treturn xerrs.Wrap(b(), \"called b\")\n}\n\nfunc b() error {\n\treturn xerrs.New(\"uh oh, something bad happened\")\n}\n```\n\n#### Formatted wrapping\n\n```go\nfunc main() {\n\tnumbers := []int{1, 2, 3}\n\tif err := a(numbers...); err != nil {\n\t\tlog.Fatalln(err)\n\t}\n}\n\nfunc a(n ...int) error {\n\tfor i, v := range n {\n\t\tif err := b(v); err != nil {\n\t\t\treturn xerrs.Wrapf(err, \"called b(%d)\", v)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc b(n int) error {\n\tif n % 2 != 0 {\n\t\treturn xerrs.New(\"number is odd\")\n\t}\n\treturn nil\n}\n```\n\n\n## Docs\n\n#### func New\n\n```go\nfunc New(string) error\n```\n\nNew creates a new xerr with a supplied message\n\nNote it will also set the stack\n\n#### func Errorf\n\n```go\nfunc Errorf(string, ...interface{}) error\n```\n\nErrorf creates a new xerr based on a formatted message\n\nNote it will also set the stack\n\n#### func Extend\n\n```go\nfunc Extend(error) error\n```\n\nExtend creates a new xerr based on a supplied error\n\nNote if error is nil then nil is returned\n\nNote it will also set the stack\n\n#### func Mask\n\n```go\nfunc Mask(error, error) error\n```\n\nMask creates a new xerr based on a supplied error but also sets the mask error as well. Only mask\nerror value is returned back when Error() is called\n\nNote if error is nil then nil is returned\n\nNote if error is xerr then its mask value is updated\n\nNote it will also set the stack\n\n#### func IsEqual\n\n```go\nfunc IsEqual(error, error) bool\n```\n\nIsEqual is a helper function to compare if two errors are equal\n\nNote if one of those errors is xerr then it's Cause is used for comparison\n\n#### func Cause\n\n```go\nfunc Cause(error) error\n```\n\nCause returns xerr's cause error\n\nNote if error is not xerr then argument error is returned back\n\n#### func SetData\n\n```go\nfunc SetData(error, string, interface{})\n```\n\nSetData sets custom data stored in xerr\n\nNote if error is not xerr then function does not do anything\n\n#### func GetData\n\n```go\nfunc GetData(error, string) (interface{}, bool)\n```\n\nGetData returns custom data stored in xerr\n\nNote if error is not xerr then (nil, false) is returned\n\n#### func Stack\n\n```go\nfunc Stack(error) []StackLocation\n```\n\nStack returns stack location array\n\nNote if error is not xerr then nil is returned\n\n#### func Details\n\n```go\nfunc Details(error, int) string\n```\n\nDetails returns a printable string which contains error, mask and stack\n\nNote maxStack can be supplied to change number of printer stack rows\n\nNote if error is not xerr then Error() is returned\n\n## What are the alternatives?\n\nxerrs library was partially inspired by [juju/errors](https://github.com/juju/errors)\n\n[pkg/errors](https://github.com/pkg/errors)\n\nAlso there are\n[new ideas and drafts for Go error handling](https://go.googlesource.com/proposal/+/master/design/go2draft.md)\nwhich might change the way error is being handled in the future.\n\n## LICENSE\n\nsee [LICENSE](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froserocket%2Fxerrs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froserocket%2Fxerrs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froserocket%2Fxerrs/lists"}