Application-level Rust errors often need more context than the raw error returned by std or another crate. The anyhow crate fits binaries and command-line tools where the user needs a readable failure report instead of a public typed error API.
anyhow::Result gives fallible functions one return type while the ? operator still propagates I/O, parsing, and library errors. The Context trait adds the operation that failed, so a missing file report can name the path instead of stopping at a generic OS error.
Use anyhow at the application boundary, such as main, task runners, and internal CLI helpers. Library crates that expect downstream callers to match individual error variants usually keep a typed error enum and reserve anyhow for binaries, tests, or examples.
Related: How to add a Rust dependency with Cargo
Related: How to check Rust code with Cargo
The directory should contain the Cargo.toml file for the application that will report contextual errors.
$ cargo add anyhow
Updating crates.io index
Adding anyhow v1.0.102 to dependencies
Features:
+ std
- backtrace
Updating crates.io index
Locking 1 package to latest Rust 1.96.0 compatible version
cargo add anyhow records the dependency in Cargo.toml and updates Cargo.lock for an application package.
use anyhow::{Context, Result}; use std::{env, fs, path::PathBuf}; fn main() -> Result<()> { let path = env::args_os() .nth(1) .map(PathBuf::from) .unwrap_or_else(|| PathBuf::from("Cargo.toml")); let contents = fs::read_to_string(&path) .with_context(|| format!("failed to read {}", path.display()))?; println!("loaded {} bytes from {}", contents.len(), path.display()); Ok(()) }
with_context() delays the formatted message until the read fails. Use context() when the added message does not need values from the current scope.
$ cargo run -- Cargo.toml
Downloading crates ...
Downloaded anyhow v1.0.102
Compiling anyhow v1.0.102
Compiling demo-cli v0.1.0 (/work/demo-cli)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.68s
Running `target/debug/demo-cli Cargo.toml`
loaded 98 bytes from Cargo.toml
The successful path returns Ok(()) from main after printing the byte count.
$ cargo run -- missing.toml
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/demo-cli missing.toml`
Error: failed to read missing.toml
Caused by:
No such file or directory (os error 2)
The first line comes from with_context(). The Caused by section keeps the original I/O error that ? propagated.