{"id":19602335,"url":"https://github.com/scottlamb/coded","last_synced_at":"2026-03-13T14:33:22.924Z","repository":{"id":57607397,"uuid":"446616121","full_name":"scottlamb/coded","owner":"scottlamb","description":"concrete Rust error type with an `ErrorKind` enum matching Google's \"canonical error codes\"","archived":false,"fork":false,"pushed_at":"2022-11-03T16:12:30.000Z","size":33,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-04T00:20:28.312Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://crates.io/crates/coded","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scottlamb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-10T23:38:15.000Z","updated_at":"2022-05-09T15:49:52.000Z","dependencies_parsed_at":"2022-08-30T08:51:41.818Z","dependency_job_id":null,"html_url":"https://github.com/scottlamb/coded","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/scottlamb/coded","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fcoded","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fcoded/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fcoded/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fcoded/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottlamb","download_url":"https://codeload.github.com/scottlamb/coded/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fcoded/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30468323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T11:00:43.441Z","status":"ssl_error","status_checked_at":"2026-03-13T11:00:23.173Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":[],"created_at":"2024-11-11T09:23:35.552Z","updated_at":"2026-03-13T14:33:22.904Z","avatar_url":"https://github.com/scottlamb.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# coded\n\nThis is a concrete error type with an `ErrorKind` enum matching\nGoogle's \"canonical error codes\". You may know these from [Google Cloud\nerrors](https://cloud.google.com/apis/design/errors),\n[`absl::Status`](https://abseil.io/docs/cpp/guides/status), or\n[gRPC status codes](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).\n\n## Status\n\nThe error code enum is exceptionally stable. The overall crate API is a work in\nprogress. Ideas welcome!\n\nI'll convert [Moonfire NVR](https://github.com/scottlamb/moonfire-nvr) to this\nshortly.\n\n## Example\n\n```rust\nuse coded::{bail, err, Error, ErrorBuilder, ErrorKind, ResultExt};\n\n/// Reads application config from its well-known paths.\nfn read_config() -\u003e Result\u003cMyConfig, Error\u003e {\n    for path in \u0026PATHS {\n        match read_json(p) {\n            Ok(c) =\u003e return Ok(c),\n            Err(e) if e.kind() == ErrorKind::NotFound =\u003e { /* keep trying */ },\n\n            // The `bail!` macro is a convenient, flexible shorthand.\n            Err(e) =\u003e bail!(e, msg(\"can't read {}\", p.display()))\n        }\n    }\n\n    // `bail!` lets us write `NotFound` without `use ErrorKind::*`.\n    bail!(NotFound, msg(\"no config file at any of {:?}\", PATHS))\n}\n\n/// Reads a JSON object from the given path.\n/// \n/// This returns an `ErrorBuilder` rather than an `Error`, avoiding a redundant\n/// entry in the error chain when it's wrapped by the caller.\nfn read_json\u003cT: Deserialize\u003e(p: \u0026Path) -\u003e Result\u003c(), ErrorBuilder\u003e {\n    // There's automatic conversion from std::io::Error to coded::ErrorBuilder which\n    // selects an appropriate ErrorKind.\n    let raw = std::fs::read(p)?;\n\n    // ResultExt::err_kind wraps any std::error::Error impl, using the supplied\n    // kind. It doesn't add a message.\n    serde_json::from_str(\u0026raw).err_kind(ErrorKind::InvalidArgument)\n}\n\nfn main() {\n    if let Err(e) = inner_main() {\n        // `Error::chain` prints not only `e` itself but also the full chain of sources.\n        eprintln!(\"Fatal error:\\n{}\", e.chain());\n        std::process::exit(1);\n    }\n}\n\nfn inner_main() -\u003e Result\u003c(), Error\u003e {\n    let config = read_config()?;\n\n    // ...\n}\n```\n\n## When should I use it?\n\n*   When you want the advantages of this single well-designed,\n    general-purpose error code enum:\n    *   *familiarity:* when you use the same error codes widely, the expectations\n        for handling them are clear.\n    *   *monitoring:* you can meaningfully aggregate errors returned by\n        different APIs with these codes.\n    *   *stability:* existing error codes and their numbers will never change.\n        The enum is marked `#[non_exhaustive]` because new codes could be\n        added, but this hasn't happened since 2015. This is great for RPC\n        or crate boundaries.\n    *   *gRPC interoperability:* many services (not only Google's) use these\n        error codes already.\n*   When you want your errors to emphasize how the caller should handle them\n    rather than details of your implementation or dependencies. See the blog\n    post [Rust Error Handling](https://www.unwoundstack.com/blog/rust-error-handling.html).\n*   When returning `Ok` has to be cheap. A `Result\u003c(), coded::Error\u003e` is\n    one word, so returning `Ok` is [faster](https://github.com/rust-lang-deprecated/failure/issues/9)\n    than with larger error types.\n*   When you want rich human-readable error messages with the code, details,\n    complete error chain, and more. Currently \"more\" can be stack traces\n    (controlled by the application's `Cargo.toml` and environment variables).\n    In the future, perhaps\n    [`tracing_error::SpanTrace`](https://crates.io/crates/tracing-error) and/or\n    arbitrary payloads.\n*   When you want to return errors easily with the `err!` and `bail!` macros.\n\n## When shouldn't I use it?\n\n*   When you don't care about error codes at all. You might be more interested\n    in [`anyhow`](https://crates.io/crates/anyhow),\n    [`eyre`](https://crates.io/crates/eyre), or\n    [`snafu::Whatever`](https://docs.rs/snafu/0.7.0/snafu/struct.Whatever.html).\n*   When you want an absolutely stable error type *right now*. As written above,\n    the actual enum values aren't changing, but it's a little early for the rest\n    of `coded`'s API to reach 1.0. (Note: if there's demand, I could split\n    the absolutely-stable `coded::{ErrorKind, ToErrorKind}` types into\n    their own crate. Then you could have a stable error type by wrapping\n    `coded::Error` in your own crate's public `Error` type.)\n*   When you need exhaustive enums with custom fields to guide the caller in\n    handling domain-specific errors, sometimes at the cost of API stability.\n*   When returning `Err` has to be cheap. `coded::Error` isn't cheap: it\n    requires heap allocation, and currently stack traces can't be disabled for\n    particular libraries or call sites.\n*   When you want to just pass along other crates' errors with `?` without\n    having to make your own wrapper around those error types and/or\n    `coded`. Due to [Rust's orphan\n    rule](https://rust-lang.github.io/chalk/book/clauses/coherence.html),\n    `coded::ToErrorKind` can only be implemented where the error is defined\n    or in `coded`. This limits ergonomics. (Once specialization is stable,\n    `?` *could* pass along other types using `ErrorKind::Unknown`, but this\n    might be more of a footgun than a help. Likewise, we could fight the\n    orphan rule with something like\n    [`inventory`](https://github.com/dtolnay/inventory), but we probably\n    shouldn't.)\n\n[Error Handling in a Correctness-Critical Rust Project](http://sled.rs/errors.html)\ndescribes how many of these apply to the [`sled`](https://crates.io/crates/sled)\ndatabase.\n\nIf you need your own error type but hate writing boilerplate, try the derive\nmacros from [`thiserror`](https://crates.io/crates/thiserror) or\n[`snafu`](https://crates.io/crates/snafu)).\n\n## How should I use it?\n\nReturn `coded::Error`. Use comments to document the error kinds your API\nreturns in certain situations. Feel free to add additional error kinds without a\nsemver break, as callers must match non-exhaustively.\n\n## What's missing?\n\n*   The ability to extend the status with typed payloads as `absl::Status`\n    supports. I'd like to use support baked into the `std::error::Error` trait\n    for this (see [RFC 2895](https://github.com/rust-lang/rfcs/pull/2895)) but\n    it doesn't exist yet. `coded` might grow its own API for this in the\n    meantime.\n*   Support for serializing and deserializing as protobufs. There are at least\n    three Rust protobuf libraries ([`prost`](https://crates.io/crates/prost),\n    [`protobuf`](https://crates.io/crates/protobuf), and\n    [`quick-protobuf`](https://crates.io/crates/quick-protobuf)). We could\n    support each via Cargo feature flags.\n    \n## License\n\nApache 2.0 or MIT, at your option.\n\n## Author\n\nScott Lamb \u0026lt;slamb@slamb.org\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottlamb%2Fcoded","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottlamb%2Fcoded","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottlamb%2Fcoded/lists"}