{"id":35248722,"url":"https://github.com/nicolab/okerr","last_synced_at":"2026-04-05T11:32:18.972Z","repository":{"id":324831040,"uuid":"1098739028","full_name":"Nicolab/okerr","owner":"Nicolab","description":"Ergonomic result / error handling helpers built on anyhow and thiserror.","archived":false,"fork":false,"pushed_at":"2025-11-25T02:09:46.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T18:37:29.577Z","etag":null,"topics":["anyhow","error-handler","error-handling","monad","result-pattern","rust","thiserror"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nicolab.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-11-18T04:42:09.000Z","updated_at":"2025-11-25T02:09:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Nicolab/okerr","commit_stats":null,"previous_names":["nicolab/okerr"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Nicolab/okerr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nicolab%2Fokerr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nicolab%2Fokerr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nicolab%2Fokerr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nicolab%2Fokerr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nicolab","download_url":"https://codeload.github.com/Nicolab/okerr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nicolab%2Fokerr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31434624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"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":["anyhow","error-handler","error-handling","monad","result-pattern","rust","thiserror"],"created_at":"2025-12-30T06:16:36.898Z","updated_at":"2026-04-05T11:32:18.965Z","avatar_url":"https://github.com/Nicolab.png","language":"Rust","readme":"# okerr - Ergonomic result / error handling\n\n[![Crates.io](https://img.shields.io/crates/v/okerr.svg)](https://crates.io/crates/okerr)\n[![Docs.rs](https://docs.rs/okerr/badge.svg)](https://docs.rs/okerr)\n[![License](https://img.shields.io/crates/l/okerr.svg)](https://github.com/nicolab/okerr/blob/main/LICENSE)\n\n`okerr` is a ergonomic result / error handling helpers built on anyhow and thiserror.\n\nMost Rust projects handle errors with `anyhow` or `eyre`, and `thiserror` (for `derive(Error)`). Sometimes we have to juggle between.\n\n`okerr` solves the problem, this crate makes this more convenient by providing consistency and an idiomatic API.\n\nThe `okerr` crate is mostly re-exported from `anyhow`, making it 100% compatible in both directions.\n\nThanks to `okerr::from_boxed_error`, it's easy to capture and convert `eyre` errors without including `eyre` as a dependency!\n\nAll of that in just a few lines of code (very lightweight, no overhead, no abstraction cost). Fully tested, of course!\n\nIdiomatic aliases for clearer code:\n\n```rust\nanyerr!(\"Oops!\"); // Instead of `anyhow!(\"Oops!\")\nerr!(\"Oops!\"); // Instead of `Err(anyhow!(\"Oops!\")) or `Err(anyerr!(\"Oops!\"))\nfail!(\"Oops!\"); // Instead of `bail!(\"Oops!\")\n\n// ---\n\nuse okerr::derive::Error;\n\n#[derive(Error, Debug)]\n\n// Instead of\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\n\n// ---\n\n// Convert from a boxed error (like eyre::Report)\nlet error = okerr::from_boxed_error(error.into())\n\n// Create/convert from any std::error::Error\nlet error = okerr::anyerr!(error)\n\n// Create/convert from a string\nlet error = okerr::anyerr!(\"Oops!\")\n\n// Wrap a Result into an okerr::Error\n// Equivalent to result.map_err(okerr::Error::new)\nlet result = okerr::wrap_err(result)\n```\n\nIt's very simple, very lightweight (just a few lines of code in the `okerr` crate), it provides consistency and a excellent DX. 100% compatible with `anyhow` and `thiserror`, convert easily error from a boxed error (like eyre::Report and others).\n\n## Related docs\n\n- [Docs.rs: okerr](https://docs.rs/okerr/latest/okerr/)\n- [Docs.rs: anyhow](https://docs.rs/anyhow/latest/anyhow/)\n- [Docs.rs: thiserror](https://docs.rs/thiserror/latest/thiserror/)\n\n## Examples\n\n### Anyhow like\n\nWith `okerr::Result`, `okerr::err!`, `okerr::fail!` and `okerr::anyerr!`:\n\n```rust\nuse okerr::{Result, err, fail, anyerr};\n\nfn divide(a: i32, b: i32) -\u003e Result\u003ci32\u003e {\n    if b == 0 {\n        err!(\"Cannot divide by zero\")\n    } else {\n        Ok(a / b)\n    }\n}\n\nfn maybe_fail(should_fail: bool) -\u003e Result\u003cString\u003e {\n  if should_fail {\n    fail!(\"Oops!\");\n  }\n\n  Ok(\"No error\".to_string())\n}\n\nfn main() {\n    let result = divide(10, 2);\n    assert!(result.is_ok());\n    assert_eq!(result.unwrap(), 5);\n\n    let result = divide(10, 0);\n    assert!(result.is_err());\n    assert_eq!(result.unwrap_err().to_string(), \"Cannot divide by zero\");\n\n    // fail! does early return\n    let result = maybe_fail(true);\n    assert!(result.is_err());\n    assert_eq!(result.unwrap_err().to_string(), \"Oops!\");\n\n    // No error\n    let result = maybe_fail(false);\n    assert!(result.is_ok());\n    assert_eq!(result.unwrap(), \"No error\");\n\n    // Same as anyhow!(...).\n    // Creates an Error directly,\n    // from a string or any std::error::Error\n    let error = anyerr!(\"Oops!\");\n    assert_eq!(error.to_string(), \"Oops!\");\n}\n```\n\n### Thiserror like\n\n\u003e NOTE: requieres the `thiserror` dependency to be added to your `Cargo.toml` (`cargo add thiserror`).\n\nWith `okerr::derive::Error`:\n\n```rust\nuse okerr::{Result, err, derive::Error};\n\n#[derive(Error, Debug)]\nenum MyError {\n    #[error(\"Cannot divide by zero\")]\n    DivideByZero,\n    #[error(\"Cannot divide by {0}\")]\n    DivideBy(i32),\n}\n\nfn divide(a: i32, b: i32) -\u003e Result\u003ci32\u003e {\n    if b == 0 {\n        err!(MyError::DivideByZero)\n    } else if b \u003c 0 {\n        err!(MyError::DivideBy(b))\n    } else {\n        Ok(a / b)\n    }\n}\n\nfn main() {\n    let result = divide(10, 2);\n    assert!(result.is_ok());\n    assert_eq!(result.unwrap(), 5);\n\n    let result = divide(10, 0);\n    assert!(result.is_err());\n    assert_eq!(result.unwrap_err().to_string(), \"Cannot divide by zero\");\n\n    let result = divide(10, -2);\n    assert!(result.is_err());\n    assert_eq!(result.unwrap_err().to_string(), \"Cannot divide by -2\");\n}\n```\n\n## Tests\n\n`okerr` is fully tested! Run all tests:\n\n```sh\ncargo test\n```\n\n## Thanks\n\nThanks to [@dtolnay](https://github.com/dtolnay), the author of [anyhow](https://github.com/dtolnay/anyhow) and [thiserror](https://github.com/dtolnay/thiserror), for providing two great ways to handle errors in Rust. 👍\n\n## LICENSE\n\n[MIT](https://github.com/nicolab/okerr/blob/main/LICENSE) (c) 2025, Nicolas Talle.\n\n## Author\n\n- [Nicolas Talle](https://ntalle.com)\n- \u003chttps://www.linkedin.com/in/ntalle/\u003e\n\n\u003e Buy me a coffee ☕ via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=PGRH4ZXP36GUC)!\n","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=PGRH4ZXP36GUC)!"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolab%2Fokerr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicolab%2Fokerr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolab%2Fokerr/lists"}