The Rust community takes its error handling seriously. There’s already a strong culture in place for emphasizing helpful error handling and reporting, with multiple libraries each offering their own take (see Jane Lusby’s thorough survey of Rust error handling/reporting libraries).
But there’s still room for improvement. The main focus of the group is carrying on error handling-related work that was in progress before the group's formation. To that end, we're working on systematically addressing error handling-related issues, as well as eliminating blockers that are holding up stalled RFCs.
Our first few meetings saw us setting a number of short- and long-term goals. These goals fall into one of three themes: making the
Error trait more universally accessible, improving error handling ergonomics, and authoring additional learning resources.
Error trait has been around since 1.0, and exposed two methods:
Error::cause. As it was originally constructed, it was too restictive for a number of reasons1. The
Failure crate addressed many of the
Error trait's shortcomings by exporting the
Fail trait, which informs many of changes that are being made to improve the
On that note, bolstering the
std::error::Error trait such that it could be adopted across the Rust community as the
Error trait has been an ongoing process since RFC 2504 was merged in August 2018.
This process also involves stabilizing many
Error trait APIs and crates that are, as of this writing, on nightly only. These include the
chain methods, which are both extremely useful for working with error types. If you’re interested in following or contributing to this work, take a look at this issue.
Another related initiative is migrating the
Error trait to
core so that it’s more widely accessible to different use cases (such as in FFI or embedded contexts).
More Ways to Access Error Contexts
Rust’s language semantics already provide a decently ergonomic error handling experience, what with the
Result type and the
? operator. The error handling group has identified a few additional features to further improve the error handling user experience.
Adding the Capability to Iterate Through the
As of this writing, the
backtrace type only implements the
Debug traits. This means that the only way to work with the
backtrace type is to print it out, which is less than ideal. An iterator API that provided the ability to iterate through stack frames would give users the ability to control how their backtraces are formatted, which is a necessary step adding
std::backtrace::Backtrace support to crates like
Upon researching strategies for how to tackle this, we found that the
backtrace crate already has a
frames method that would work nicely for implementing the
Iterator API. It should be a relatively straightforward ordeal to expose an identical method in
A PR for this has been opened for anyone who would like to check it out.
Generic Member Access
Currently, when we want to fetch some additional context related to an error, there are specific methods that need to be called in order to fetch that context. For example, to see the backtrace for an error, we’d call the
let backtrace = some_error.backtrace();. The problem with this approach is that it's not possible to support types that are defined outside of
std. Even for types that exist within
std, a method to access each respective type needs to be defined, which makes things cumbersome and harder to maintain.
As the name implies, generic member access, when it gets implemented, is a type-agnostic way to access different pieces of context from an
Error trait object. The analogy that clicked for me is when you’re parsing a string into a number, with something like:
let ten = "10".parse::<i32>();
Or when you’re collecting the contents yielded by an iterator:
use std::collections::HashSet; let a_to_z_set = ('a'..='z').collect::<HashSet<_>>();
In a similar vein, you’d be able to access some piece of context from an error by specifying its type ID:
let span_trace = some_error.context::<&SpanTrace>();
This could be used to fetch other pieces of context related to the error such as its backtrace, the error’s sources, status codes, alternate formatting representations (such as
This feature will enable other features we plan on adding down the line, such as exposing a way to report back all of the locations from which errors originated from in a program, as well as exposing a more consistent error reporting format besides just
Jane has been putting in a lot of work on pushing these ideas forward. You can check out the associated RFC.
Authoring a Book on Rust Error Handling Best Practices
Last but not least, there’s a lot of interest in the group around authoring The Rust Error Book. The aim of the book would be to codify and communicate different error handling best practices based on the respective use-case. This could include FFI use-cases, or best practices around returning error codes from programs.
This is an ongoing effort that will see a lot of progress in the coming weeks and months!
We're excited by the opportunities to continue to iterate on and improve Rust's error handling ergonomics and culture! If you're interested in helping out and/or joining in on the conversation, please come by and introduce yourself in our Zulip stream. You can also keep track of our progress via our GitHub repo.
Lastly, we'll be presenting some forthcoming news about a universally consistent error reporting format in our next update, so stay tuned for that!
Error::description method only supported string slices, which meant that it was not straightforward to create dynamic error messages that included additional context. This method was deprecated in favor of
Error::cause method, now known as
Error::source, doesn't enforce errors having a
'static lifetime, which means that downcasting error sources is impossible, making it much more difficult to handle errors using dynamic error handlers.