Rust Errors: anyhow Revelation

amaendeepm

amaendeepm

Posted on October 7, 2024

Rust Errors: anyhow Revelation

How I stopped writing Rust like it was Golang and finally embraced anyhow::Error.

When I first started with Rust, my error handling looked something like this:

fn do_stuff() -> Result<String, String> {
    let step1 = step1()?;
    if step1.is_error() {
        return Err("Step 1 failed".to_string());
    }

    let step2 = step2(step1.unwrap())?;
    if step2.is_error() {
        return Err("Step 2 failed".to_string());
    }

    Ok("All good!".to_string())
}
Enter fullscreen mode Exit fullscreen mode

Or maybe when I learned Rust further my return type was still Result<Arc<str>, Arc<str>> , but still following same style of error checking and handling!

Yikes, right? It looked like I was writing Go, but with extra steps. Having an error as a type provided thru anyhow::Error, and code conditions and sizing came way down smaller and so much more readable:

use anyhow::{Result, Context};

fn do_stuff() -> Result<String> {
    let step1 = step1().context("Step 1 failed")?;
    let step2 = step2(step1).context("Step 2 failed")?;
    Ok("All good!".to_string())
}
Enter fullscreen mode Exit fullscreen mode

So much cleaner! No more explicit checks, and I can add context where it matters. The best part? I can still use Result<String, String> for those rare cases where I need super explicit errors.

fn critical_stuff() -> Result<String, String> {
    // Detailed custom errors here
}
Enter fullscreen mode Exit fullscreen mode

Now, let's talk pros and cons. On the professional side, anyhow has some significant benefits:

It reduces boilerplate, making code more readable and maintainable.
The Context trait allows for rich error messages without custom error types.
It's great for rapid prototyping and applications where detailed error handling isn't critical.

However, it's not all roses. There are some potential drawbacks:

  • Loss of static type checking for errors. You can't exhaustively match on error types, which can be a problem in libraries or safety-critical code.
  • Performance overhead. While minimal, anyhow::Error does introduce some runtime cost compared to statically typed errors.
  • It can make it easier to be less thoughtful about error design. In complex systems, well-designed error types can be invaluable.

Overall, in my experience, the benefits outweigh the drawbacks, especially in application code. For libraries or performance-critical systems, you might want to stick with custom error types.

If you're still writing Rust errors like it's Go, give anyhow::Error a shot

💖 💪 🙅 🚩
amaendeepm
amaendeepm

Posted on October 7, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related