Use “anyhow” in Rust
“anyhow” has gained popularity for its simplicity and flexibility in error management, and it has become a widely used library for handling errors in Rust applications”.

“Anyhow” simplifies error management by allowing the use of the ? operator to propagate errors concisely.
Webdock โ Fast Cloud VPS Linux Hosting
Example Code
from terminal :
cargo add anyhow
use anyhow::Result;
fn main() -> Result<()> {
let result = divide(10, 2)?;
println!("Result: {}", result);
Ok(())
}
fn divide(a: i32, b: i32) -> Result<i32> {
if b == 0 {
anyhow::bail!("Division by zero");
}
Ok(a / b)
}

when you use the ? operator to propagate errors, the error “bubbles up” through the function call stack until it’s either handled with a Result type or returned from the main function.
Note : You can use the ? operator with any type that implements the std::ops::Try trait, not just “anyhow“.
Let’s take another example to illustrate how errors bubble up in Rust using the “anyhow” crate:
use anyhow::{Result, Context};
fn main() -> Result<()> {
let result = divide_and_multiply(10, 5, 2)?;
println!("Result: {}", result);
Ok(())
}
fn divide_and_multiply(a: i32, b: i32, c: i32) -> Result<i32> {
let x = divide(a, b)?;
let y = multiply(x, c)?;
Ok(y)
}
fn divide(a: i32, b: i32) -> Result<i32> {
if b == 0 {
anyhow::bail!("Division by zero");
}
Ok(a / b)
}
fn multiply(a: i32, b: i32) -> Result<i32> {
if a == 0 || b == 0 {
anyhow::bail!("Multiplication by zero");
}
Ok(a * b)
}
Error propagation
In this example, we have three functions: divide_and_multiply, divide, and multiply. Here’s how error propagation works:
- In the
divide_and_multiplyfunction, we first calldivide(a, b)?. Ifdivideencounters an error (e.g., division by zero), it will return an error that “bubbles up” to the caller. The same goes for themultiplyfunction. - When an error occurs, it is immediately returned to the calling function, and this propagation continues until the error is either handled in the
mainfunction or causes the program to exit. - In the
mainfunction, we usedivide_and_multiply(10, 5, 2)?to call the top-level function. If any of the lower-level functions return an error, it will be bubbled up to themainfunction. The?operator automatically converts these errors into aResult, and if an error occurs, it will exit the program.
This error propagation mechanism simplifies error handling and allows you to focus on handling errors at the appropriate level in your code without excessive manual error checking and handling in each function.
anyhow::Bail! macro
Using anyhow::bail!: anyhow::bail! is a convenient macro provided by the “anyhow” crate to create and immediately return an error with a specific message. This is a straightforward way to return an error without needing to create an anyhow::Error object explicitly. For example:
fn divide(a: i32, b: i32) -> Result<i32> {
if b == 0 {
anyhow::bail!("Division by zero");
}
Ok(a / b)
}
anyhow::Error
Using anyhow::Error Directly: If you need more control over error creation or want to add additional context to the error, you can create an anyhow::Error object explicitly. This allows you to add context, chain errors, and customize the error message further. Here’s an example:
use anyhow::Result;
fn divide(a: i32, b: i32) -> Result<i32> {
if b == 0 {
return Err(anyhow::Error::msg("Division by zero"));
}
Ok(a / b)
}
Both approaches are valid and serve different purposes. The choice between them depends on the complexity of error handling and the amount of additional context you want to provide with the error. anyhow::bail! is a more concise way to return an error with a simple message, while creating an anyhow::Error object directly offers more flexibility for custom error handling and context addition.
Try the code in Rust Playground

