Frequently Asked Questions
Why should I use Problemo instead of the many alternatives?
Maybe because you appreciate its goals and design? We’re not in competition with others and we’re not trying to win you over. (Unless there were a trophy involved, then things would get heated!)
Error handling is a very opinionated topic and one size does not fit all. As it stands, you’re going to have to do the homework to evaluate each library and decide which is “best”.
At the very least we urge you to consider not only the experience of writing your code but also the experience of users of your code. How easy is it for them to inspect and handle the errors you return?
Popular Alternatives
-
error-stack, like Problemo, supports chaining and attachments. It does, however, require you to provide a concrete error type for your returns, which it (confusingly in our opinion) calls “the context”. It supports returning groups of errors as long as they are of that same “context” type, as well as backtraces and pretty printing.
-
rootcause works similarly to error-stack in practice while also supporting type-less wrappers like Problemo. It also features first-class (but limited) support for non-static errors without having to convert them, which is achieved through an innovative use of generic markers. Its scope is broad and it’s relatively complex. It includes a customizable error formatter and other powerful features.
-
anyhow is simple in its usage but is in fact a sophisticated library. It solves the problem of not being able to set the
source()of a stdErrorby rewriting its dynamic dispatch vtable. On top of this, it lets you add non-errors to the causation chain via an internal wrapper, which (again, confusingly in our opinion) it calls “a context”. It only supports one attachment type, a backtrace, which is handled implicitly and automatically. -
SNAFU works similarly to Anyhow in practice but takes a different design approach by introducing its own set of traits as a replacement for std
Errorwhile also allowing for compatibility with it. This allows you to build custom, rich error types on top of SNAFU. -
eyre is a fork of Anyhow with support for customizable formatting.
Why doesn’t Problem wrap a concrete error type? Wouldn’t it be better to have the compiler validate correct usage?
To be clear, Problemo embraces the importance of concrete types for both errors and attachments. Rust’s type system is our essential tool for inspecting and handling the causation chain.
But that doesn’t mean it’s a good idea to require the top of the causation chain to be of a certain type. Our experience in large projects with such a requirement has led us to believe that it’s an arbitrary, cumbersome, and ultimately pointless practice, especially for high-level functions that can have long causation chains. More often than not, the details we and our users care about are deeper in the chain.
Simply put, any returned Err signifies failure, period. In practice just having the compiler test that the topmost error is of a “correct” type guarantees very little if we’re not actually handling the details of that failure. All we’ve done is add clutter and unnecessary complexity.
This dilemma isn’t unique to Rust. For example, the Java world has had a long-running debate about the usefulness of checked exceptions (example). It all hinges on whether you believe that having the compiler enforce the recognition of the topmost error type encourages programmers to handle that error. Do you? We don’t.
Why no pretty formatting of causation chains with attachments?
Formatting is deliberately out of scope precisely because it’s important.
We’re not going to be able to do it justice because it’s very specific to the reason for formatting, the reporting environment, and even personal taste. Are you printing out errors to a console for debugging? Are you displaying an error to a user in a dialog box? Are you logging errors to a textual file or a database for auditing? These are all very different use cases, some of which may require you to specifically hide sensitive information, provide text in multiple human languages, etc.
We might provide add-on libraries to help with this in the future, but we want to keep the core unopinionated in this regard. For ideas on how to implement formatting, check out the function_attachment and supertrait examples.
Why doesn’t Problemo come with macros such as bail!()?
It seems that most error-handling libraries have these. They do the job of optimizing the creation and returning of errors so that it would take the smallest number of keystrokes. Problemo instead prefers verbosity, clarity, and debuggability by encouraging the use of explicit function calls.
We use macros only when functions can’t work. Generally speaking our code is deliberately straightforward and non-magical and it should be easy for any Rust programmer to read and understand. Error handling is foundational and we believe that it should not be a mysterious black box.
You are of course free to create your own macros for Problemo but we don’t want to promote them in our published API.
no_std?
Problemo’s stated goal is to improve the use of std Error. That said, it’s easy to imagine causation chains of types with fewer constraints. If the need for no_std arises let’s work together to make it possible.
I like Problemo but it’s missing my favorite feature!
That’s not a question! Anyway, we are happy to hear your suggestions. Please be nice about it and do keep in mind that we want to keep Problemo lean, simple, and focused on the essentials. If the feature is something that can be built on top of Problemo, perhaps as a supplementary library, then that will likely be the preferred route.
Spanish?
Actually it’s Spanglish. And even more actually it’s Esperanto. Mi havas naŭdek naŭ problemojn, sed hundino ne estas unu.
“AI”?
Please, no.