{"id":33922740,"url":"https://github.com/nu11ptr/uni_error","last_synced_at":"2026-04-06T06:33:04.654Z","repository":{"id":321320812,"uuid":"1084532672","full_name":"nu11ptr/uni_error","owner":"nu11ptr","description":"A simple, universal error type for Rust","archived":false,"fork":false,"pushed_at":"2026-01-05T02:39:13.000Z","size":152,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-07T05:37:48.202Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/nu11ptr.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-27T20:06:34.000Z","updated_at":"2026-01-05T02:39:16.000Z","dependencies_parsed_at":"2025-12-09T15:03:00.072Z","dependency_job_id":null,"html_url":"https://github.com/nu11ptr/uni_error","commit_stats":null,"previous_names":["nu11ptr/uni_error"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nu11ptr/uni_error","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nu11ptr%2Funi_error","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nu11ptr%2Funi_error/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nu11ptr%2Funi_error/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nu11ptr%2Funi_error/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nu11ptr","download_url":"https://codeload.github.com/nu11ptr/uni_error/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nu11ptr%2Funi_error/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31463014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"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-12-12T09:11:03.744Z","updated_at":"2026-04-06T06:33:04.648Z","avatar_url":"https://github.com/nu11ptr.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# uni_error\n\n[![Crate](https://img.shields.io/crates/v/uni_error)](https://crates.io/crates/uni_error)\n[![Docs](https://docs.rs/uni_error/badge.svg)](https://docs.rs/uni_error)\n[![Build](https://github.com/nu11ptr/uni_error/workflows/CI/badge.svg)](https://github.com/nu11ptr/uni_error/actions)\n[![codecov](https://codecov.io/github/nu11ptr/uni_error/graph/badge.svg?token=LIBztRdGNS)](https://codecov.io/github/nu11ptr/uni_error)\n\nA simple, universal error type for Rust\n\n## Overview\n\nRust has a great system for handling conditional success in the form of `Result\u003cT, E\u003e`, but using this in practice often leads to reinventing the wheel, especially when the program's needs are intially unknown.\n\nI wrote this crate for myself to be my universal error type after I noticed these trends in my programs:\n\n1. Most simple applications just need a text error for the user. That's it.\n\n2. When building an API, dealing with FFI, or just programmatically evaluate errors, it can be necessary to have an error \"kind\" to disambiguate sub-errors.\n\n3. It can sometimes be helpful to evaluate the chain of errors for determining the root cause.\n\nThe typical crates to solve these problems are `anyhow` and `thiserror`. These are great crates, but I wanted better integration between the universal error and the kind (essentially an `anyhow` that is \"kind-aware\"). This crate is more like `anyhow` than `thiserror`, as the latter could be seen as complementary and used to create the inner \"kind\".\n\n## Install\n\n```shell\ncargo add uni_error\n```\n\n## Features\n\n* Simple/ergonomic API\n* Can wrap any type that implements [Display](https://doc.rust-lang.org/stable/std/fmt/trait.Display.html) or [Error](https://doc.rust-lang.org/stable/std/error/trait.Error.html)\n* Provides error cause chain with metadata and downcasting\n* Both type safe and dynamic (string/integer) error kind\n* Dereferences to stdlib [Error](https://doc.rust-lang.org/stable/std/error/trait.Error.html) trait\n* Implements [Clone](https://doc.rust-lang.org/stable/std/clone/trait.Clone.html)\n* Optional [Backtrace](https://doc.rust-lang.org/stable/std/backtrace/) capture\n* Optional: Auto convert into [http::StatusCode](https://docs.rs/http/latest/http/status/struct.StatusCode.html), [axum::response::Response](https://docs.rs/http/latest/http/response/struct.Response.html), or [tonic::Status](https://docs.rs/tonic/latest/tonic/struct.Status.html) for usage in an API\n* No required dependencies\n* No macros\n* No `unsafe` (forbidden)\n* Optionally `no_std` (only backtrace capability lost)\n\n## Examples\n\nThe basics:\n\n```rust\nuse uni_error::*;\n\nfn do_something() -\u003e SimpleResult\u003c()\u003e {\n    std::fs::read(\"/tmp/nonexist\")?;\n    Ok(())\n}\n\nfn main() {\n    println!(\"{}\", do_something().unwrap_err());\n}\n```\n\nAdd some context:\n\n```rust\nuse uni_error::*;\n\nfn do_something() -\u003e SimpleResult\u003cVec\u003cu8\u003e\u003e {\n    std::fs::read(\"/tmp/nonexist\")\n        .kind_default_context(\"Oops... I wanted this to work!\")\n}\n\nfn main() {\n    println!(\"{}\", do_something().unwrap_err());\n}\n```\n\nWrap a type that doesn't implement `std::error::Error`:\n\n```rust\nuse uni_error::*;\n\nfn do_something() -\u003e Result\u003c(), String\u003e {\n    // Try to do something very important here...\n    \n    Err(\"Doh! It didn't work\".to_string())\n}\n\nfn try_do_something() -\u003e SimpleResult\u003c()\u003e {\n    do_something().kind_default_context_disp(\"Oops... I wanted this to work!\")\n}\n\nfn main() {\n    println!(\"{}\", try_do_something().unwrap_err());\n}\n```\n\nOr use your own kind:\n\n```rust\nuse std::borrow::Cow;\n\nuse uni_error::*;\n\n#[derive(Debug, Default)]\nenum MyKind {\n    #[default]\n    SomethingBad,\n    SomethingWorse(\u0026'static str),\n}\n\nimpl UniKind for MyKind {\n    fn context(\u0026self, cause: Option\u003cCause\u003c'_\u003e\u003e) -\u003e Option\u003cCow\u003c'static, str\u003e\u003e {\n        match self {\n            MyKind::SomethingBad =\u003e None,\n            MyKind::SomethingWorse(msg) =\u003e Some(Cow::Borrowed(msg))\n        }\n    }\n}\n\nfn do_something() -\u003e UniResult\u003cVec\u003cu8\u003e, MyKind\u003e {\n    std::fs::read(\"/tmp/nonexist\")\n        .kind(MyKind::SomethingWorse(\"That was REALLY bad!\"))\n}\n\nfn main() {\n    println!(\"{}\", do_something().unwrap_err());\n}\n\n```\n\n## FAQ\n\n### How do I simply propigate errors/options/results (without further context) using the question mark?\n\nIf the error type implements `std::error::Error`, or is `UniError\u003cT\u003e` --\u003e `UniError\u003cT\u003e`:\n\n```text\nresult?\n```\n\n`UniError\u003cT\u003e` --\u003e `UniError\u003cU\u003e` (`U` implements `Default`):\n\n```text\nresult.kind_default()?\n```\n\n`UniError\u003cT\u003e` --\u003e `UniError\u003cU\u003e` (`U` implements `From\u003cT\u003e`):\n\n```text\nresult.kind_into()?\n```\n\n\n`Option\u003cV\u003e`:\n\n```text\noption.kind_default()?\n```\n\nFallback for `std::fmt::Display` types:\n\n```text\nresult.kind_default_disp()?\n```\n\n### How does equality work?\n\n`UniError\u003cT\u003e`: if kind is equal, errors are equal\n\n`SimpleError`: if context is equal, errors are equal\n\n## Status\n\nThis is currently experimental, however, I am using this as my primary error type in all my work and a startup, so it will become production shortly.\n\n## Contributions\n\nContributions are welcome as long they align with my vision for this crate.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnu11ptr%2Funi_error","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnu11ptr%2Funi_error","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnu11ptr%2Funi_error/lists"}