{"id":36444618,"url":"https://github.com/sudoless/oops","last_synced_at":"2026-01-11T22:03:26.017Z","repository":{"id":59044136,"uuid":"398856030","full_name":"sudoless/oops","owner":"sudoless","description":"❌ Oops is the latest error quality of life library from SUDOLESS™","archived":false,"fork":false,"pushed_at":"2024-03-07T06:23:08.000Z","size":169,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-24T13:12:10.819Z","etag":null,"topics":["errors","golang","hacktoberfest","hacktoberfest2022","library"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sudoless.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}},"created_at":"2021-08-22T17:13:34.000Z","updated_at":"2023-01-30T11:49:26.000Z","dependencies_parsed_at":"2024-03-05T12:29:08.887Z","dependency_job_id":"7a6f1730-17c0-422e-a0e2-4c38694c2473","html_url":"https://github.com/sudoless/oops","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/sudoless/oops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoless%2Foops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoless%2Foops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoless%2Foops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoless%2Foops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sudoless","download_url":"https://codeload.github.com/sudoless/oops/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoless%2Foops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28324848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T18:42:50.174Z","status":"ssl_error","status_checked_at":"2026-01-11T18:39:13.842Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["errors","golang","hacktoberfest","hacktoberfest2022","library"],"created_at":"2026-01-11T22:03:25.936Z","updated_at":"2026-01-11T22:03:26.010Z","avatar_url":"https://github.com/sudoless.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oops\n\nA custom developed library by SUDOLESS, tailored from our experience and needs.\nWhilst using our first iteration of the bespoke error library (formally called `qer`), we noticed\na set of key issues and features that are important when dealing with errors in our services.\n\nBefore using any Go error library in a large or \"future-proof codebase\", please consider the proposed draft for\n\"[Go2 Errors](https://go.googlesource.com/proposal/+/master/design/go2draft.md)\" and the\n[feedback wiki](https://github.com/golang/go/wiki/Go2ErrorHandlingFeedback) for said draft. My personal opinion/feedback\nis also [listed](https://gist.github.com/cpl/54ed073e20f03fb6f95257037d311420).\n\n\u003e This library is subject to breaking changes until it reaches v1.\n\n## Why this library\n\n### Perspective\n\nErrors exist in two (equally real, equally important) perspectives. There is the \"_CLIENT_\" view and,\nthe \"_SERVER/DEVELOPER/SYSOPS_\" view.\n\nYour clients/consumers should get relevant information as to **why**\nthe issue occurred, **what** are the results/consequences of the error and, **how** they can fix it.\n\nYou as the developer, system and/or admin, care as much about the above as the client, but you also care\nabout \"unexpected\" errors, and a more detailed view of the situation.\n\nAs such it is important to track  both internal information such as types, structs, lines of codes,\nstack traces, etc for internal use and debugging, but it's also important to provide users with\n\"dumbed down\" versions of the error.\n\n## Usage\n\n### Fetch\n\nFetch the core library using:\n\n```shell\ngo get go.sdls.io/oops/pkg/oops\n```\n\n### Define your errors\n\nIt's important to note, that with this library, errors can be defined globally. This allows:\n- quickly identifying the errors of a package (usually grouped in a `errors.go` file, or at the top of each source file where the error is used mainly)\n- using native Go error checks like `errors.Is` or `errors.As`\n\n```go\nvar (\n\tErrAuthMissing        = oops.Define(\"type\", \"auth\", \"code\", \"auth_missing\", \"status\", 401)\n\tErrAuthBadCredentials = oops.Define(\"type\", \"auth\", \"code\", \"auth_bad\", \"status\", 401)\n\tErrAuthExpired        = oops.Define(\"type\", \"auth\", \"code\", \"auth_expired\", \"status\", 401)\n)\n```\n\nIn this example, we've defined three errors. In your projects/organization you may decide to build a helper function\nthat enforces the presence of certain fields, or even a more advanced Registry struct that holds all the errors.\n\n### Yeet *your* errors\n\nIn `oops` we [`Yeet`](https://youtu.be/D8KxdXEBkhw) our errors. By default, when using `oops.Define()` you get\na `oops.ErrorDefined`, not something you should use directly as an `error`.\n\nThe reasons behind this is to have a verifiable error (`oops.ErrorDefined`) to which all other errors point. That's why\nYeet (or Wrap) must be called on a defined error when you want to _use it_.\n\n```go\npackage example\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"go.sdls.io/oops/pkg/oops\"\n)\n\nvar (\n\tErrAuthMissing        = oops.Define(\"type\", \"auth\", \"code\", \"auth_missing\", \"status\", 401)\n\tErrAuthBadCredentials = oops.Define(\"type\", \"auth\", \"code\", \"auth_bad\", \"status\", 401)\n\tErrAuthExpired        = oops.Define(\"type\", \"auth\", \"code\", \"auth_expired\", \"status\", 401)\n)\n\nfunc validateAuth(r *http.Request) error {\n\tauthHeader := r.Header.Get(\"Authorization\")\n\tif authHeader == \"\" {\n\t\treturn ErrAuthMissing.Yeetf(\"empty auth header\")\n\t}\n\tif !strings.HasPrefix(authHeader, \"Bearer \") {\n\t\treturn ErrAuthBadCredentials.Yeetf(\"bad auth header [%s], expected Bearer\", authHeader)\n\t}\n\n\ttoken := strings.TrimPrefix(authHeader, \"Bearer \")\n\t\n\ttokenInfo, err := authManager.ParseToken(token)\n\tif err != nil {\n\t\treturn oops.Explainf(err, \"parsing token\")\n\t}\n\n\tif tokenInfo.Expiry.Before(time.Now()) {\n\t\treturn ErrAuthExpired.Yeetf(\"token expired at %s\", tokenInfo.Expiry.Format(time.RFC3339))\n\t}\n\t\n\treturn nil\n}\n```\n\nAs you can see above, we always call Yeet, with some explanation as to \"the error occurred while doing X\" and we can\neven include formatted args.\n\n\n### Wrap *their* errors\n\nIn the \"Yeet *your* errors\" example, we see how to return errors when _our_ code is the source of the error. But\nsometimes you'll want to pass an error from the stdlib or a third party library. In that case, you can wrap the error\nwith `Wrap`.\n\n### Custom Formatter\n\nBy default, the defined errors have a rudimentary string formatter that provides little (`Error.Explanation`) to no information regarding the error. Our recommended pattern is to have a dedicated package (be it locally in the project or as a organization level library) that wraps our top level functions calls such as `oops.Define` with typed arguments that represent **your** error handling params.\n\nEg: you might define `func Define(status int, code string) oops.ErrorDefined` and use that in your codebase with a formatter that then returns those `status` and `code` params the expected way.\n\n## LICENSE\n\nThis library is provided under BSD 3-Clause License, for more details see the LICENSE file.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudoless%2Foops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsudoless%2Foops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudoless%2Foops/lists"}