{"id":23142026,"url":"https://github.com/stevenacoffman/khanerr","last_synced_at":"2025-08-13T14:20:07.548Z","repository":{"id":268030231,"uuid":"628719182","full_name":"StevenACoffman/khanerr","owner":"StevenACoffman","description":"Khan Sentinel ErrorKinds with wrapping, fields for logging, and stacktraces","archived":false,"fork":false,"pushed_at":"2023-04-19T17:00:23.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T06:39:45.171Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StevenACoffman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-04-16T20:02:49.000Z","updated_at":"2023-04-16T20:03:57.000Z","dependencies_parsed_at":"2024-12-13T22:39:37.055Z","dependency_job_id":"b74d92c6-f185-417d-8de8-8c77d7772a09","html_url":"https://github.com/StevenACoffman/khanerr","commit_stats":null,"previous_names":["stevenacoffman/khanerr"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Fkhanerr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Fkhanerr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Fkhanerr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Fkhanerr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StevenACoffman","download_url":"https://codeload.github.com/StevenACoffman/khanerr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247171124,"owners_count":20895587,"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-12-17T14:16:36.028Z","updated_at":"2025-04-04T11:33:04.785Z","avatar_url":"https://github.com/StevenACoffman.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# khanerr - gRPC status code Sentinel Errors with Fields and StackTraces\n\nKhan uses an internal error implementation, which is a feature-ful, everything-and-the-kitchen-sink error package.\n\nPackage errors is a reimplementation of Khan's error package, but here, it is based on\nthe more minimalist `github.com/StevenACoffman/simplerr` which also has nicer StackTraces, and flattens Fields.\n\n`khanerr` provides errors with key value Fields, StackTraces, and Sentinel errors\nthat correspond to the gRPC status codes.\n\nYou can also use this package as a drop in replacement for the `Unwrap`, `As`, and `Is` functions from the stdlib `errors` packages.\n\nThis package is influenced by https://middlemost.com/failure-is-your-domain/.  \n\n### Sentinel Error values\n\nError kinds are sentinel error values\ninfluenced by gRPC status codes, documented at\nhttps://github.com/grpc/grpc/blob/master/doc/statuscodes.md.\n\nAn error kind (\"InternalKind\", \"InvalidKind\", etc) is used for matching\nerrors as well as giving us information in the logs about what kind\nof thing went wrong.\n\n### New Error Creation\n\nThere are functions for each error kind (e.g. `NotFoundKind`) to create errors, e.g. `NotFound`,\n`Internal`, etc. All arguments are optional:\n\n\te1 := errors.Internal(\"Message\")\n\te2 := errors.Invalid(aWrappedErr)\n\te3 := errors.NotFound(\"Message\", errors.Fields{{\"kaid\": \"123\"})\n\nEach of these functions takes an arbitrary number of args, in an\narbitrary order. The args can be:\n1. an error object to wrap\n2. a string to use as the error message\n3. an errors.Fields{} object of key/value pairs to associate with the error\n4. an errors.Source(\"source-location\") to override the default source-loc\n\nYou should always provide one of (1) and (2); you can provide both\nif it's helpful.  (3) is used to detail things like the name of the\nitem that couldn't be found, or the affected kaid, etc. Don't\nembed these details in the error message - by putting them in\nfields you make it much easier to search logs for them.\n\nIf you specify any one type multiple times, only the last one wins.\n\n### --- IS / AS / ETC ---\n\nThis package exposes the `Is`, `As` and `Unwrap` functions from\nthe stdlib errors package.\n\nYou can use the `Is` function to test against sentinel errors and wrapped\nregular errors. Then when handling the error you can test it against the\nsentinel using the `Is` function:\n\n\terr := SomeFunction()\n\tif errors.Is(err, UnauthorizedKind)  {\n\t    // The error or an error it wraps has the UnauthorizedKind kind.\n\t}\n\nIn general you should prefer to test against\nsentinel errors to know what action to\ntake based on error kind.\n\nThe `Unwrap` function works normally and returns wrapped errors.\n\nThe `As` function works normally, but isn't very useful with Khan errors.\nSince the `errorKind` type is private you can't use `As` to search for it.\nMoreover since error kinds aren't types you can't use them with `As`.\nHowever you can use `As` to find wrapped errors of other public error\ntypes.\n\n### --- WRAP ---\n\nThis package also provides a utility to \"wrap\" an existing khanError\nto add more fields:\n\n\terrors.Wrap(err, \"newfield\", \"newvalue\", \"did i just wrap?\", true)\n\nThis is equivalent to\n\n\terrors.\u003cSameKindAsErr\u003e(\"\", err,\n\t    errors.Fields{\"newfield\": \"newvalue\", \"did i just wrap?\": true})\n\n### GetFields\nWhen logging, it is recommended to use GetFields(err) to collect all the Fields\nof nested errors but ensure that the last key value pair wins.\n\nFor instance, if a `Field{\"message\":\"oh no!\"}` is set on an error that is wrapped inside a new\nerror that has `Field{\"message\":\"nevermind\"}`, then the value for `message` key is `nevermind`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevenacoffman%2Fkhanerr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstevenacoffman%2Fkhanerr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevenacoffman%2Fkhanerr/lists"}