Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

anyhow: Return nested/wrapped errors

use anyhow::Context;

fancy_module::run()
.await
.with_context(|| {
    format!("An error has been found")
})?;

From what I understand, when run returns an error, we return "An error has been found". But this message is not really meaningful. I would like to also return the error that run returns. Something like format!("An error has been found {}", e). How do I get e returned by run?

I could do that in multiple lines of code. By fetching the result of run and then having a match statement. Is there a nicer way of doing that?

like image 781
Luna Lovegood Avatar asked Oct 17 '25 02:10

Luna Lovegood


2 Answers

From what I understand, when run returns an error, we return "An error has been found".

Not correct! context and with_context create a wrapper around the underlying error value to introduce additional context, but the original error is kept within!

Once you try displaying the error, you will see something of this sort:

Error: An error has been found

Caused by:
    No such file or directory (os error 2)

(This also shows that "An error has been found" is a poor choice of words for creating additional context.)

I would like to also return the error that run returns. Something like format!("An error has been found {}", e).

That used to be a reasonable design decision in the past, but the current guidelines for error type design are against including the source error in the display message, unless that source error is also not reachable in the source error chain. The context methods will put the error in the source chain, so including that error's message into the top level error's message is ill advised.

How do I get e returned by run?

See the chain method in order to traverse the chain of source errors and so enable you to peek into underlying causes. Still, anyhow's error type was mostly designed to be opaque. If you need better introspection into what the error entails or easier pattern matching on errors, consider using a structural error type instead of anyhow::Error (snafu or thiserror can help you build them).

See also:

  • Should an Error with a source include that source in the Display output?
  • What is the difference between "context" and "with_context" in anyhow?
  • Simplier way to return custom error type with anyhow::Error?
like image 153
E_net4 stands with Ukraine Avatar answered Oct 18 '25 15:10

E_net4 stands with Ukraine


Not accessing the error message correctly, which is easy to do, can make you think that it is the case that the error messages are not propagated to parent functions.

if let Err(e) = fancy_function::run().await.context("An error has been found")? {
  let msg: String = format!("{}", e.to_string());
  // contains ONLY "An error has been found"
  let stacktrace: String = format!("{:?}", e);
  // contains the numbered list of context messages that lead to the error
}
like image 43
user3152459 Avatar answered Oct 18 '25 16:10

user3152459



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!