rusterror-handlinganyhow

Getting the anyhow Rust crate to format an error like it does when when exiting the main function


Adding the anyhow crate to a blank Rust project and running the following code gives you the output Error: error, which I want:

use anyhow::anyhow;

fn error() -> anyhow::Result<()> {
    Err(anyhow!("error"))
}

fn main() -> anyhow::Result<()> {
    error()
}

However, running the following code only outputs error:

use anyhow::anyhow;

fn error() -> anyhow::Result<()> {
    Err(anyhow!("error"))
}

fn main() {
    if let Err(error) = error() {
        println!("{:?}", error);
    }
}

I also tried using "{}" instead, but that also only lead to error being printed.

The documentation says the following:

The Debug format “{:?}” includes your backtrace if one was captured. Note that this is the representation you get by default if you return an error from fn main instead of printing it explicitly yourself.

Error: Failed to read instrs from ./path/to/instrs.json

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

I couldn't find the part of the source code that added the extra Error: , otherwise I could probably figure it out by myself.


Solution

  • The extra Error: is not related to anyhow, but rather how main() behaves if the returned Result is an Err. You can find the exact code within the implementation of Termination for Result:

    impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
        fn report(self) -> ExitCode {
            match self {
                Ok(val) => val.report(),
                Err(err) => {
                    io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}"));
                    ExitCode::FAILURE
                }
            }
        }
    }
    

    So if you want Error: included in the output in a different context, you'll have to add it yourself.

    See also: