What it is
anyhow provides a boxed, dynamically typed error for application code, with easy context attachment and a captured backtrace.
Return anyhow::Result<T> and use ? freely across error types. The context method adds human-readable layers describing what was being attempted.
Installation
cargo add anyhowGetting started
The smallest useful thing you can do with it, and what each part means.
rust
use anyhow::{Context, Result, bail, ensure};
fn load_config(path: &Path) -> Result<Config> {
let text = std::fs::read_to_string(path)
.with_context(|| format!("reading config from {}", path.display()))?;
let config: Config = toml::from_str(&text)
.context("parsing config as TOML")?;
ensure!(config.port > 0, "port must be positive");
if config.workers == 0 { bail!("workers must be at least 1"); }
Ok(config)
}
// Error: reading config from /etc/app.toml
// Caused by: No such file or directory (os error 2)Advanced usage
Where the library earns its place over a simpler alternative.
rust
fn main() -> anyhow::Result<()> {
if let Err(e) = run() {
// Look for a concrete type inside the boxed error.
if let Some(io) = e.downcast_ref::<std::io::Error>() {
if io.kind() == std::io::ErrorKind::NotFound {
return Ok(()); // acceptable
}
}
return Err(e); // main prints the chain and the backtrace
}
Ok(())
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Callers cannot match on the failure
- That is the trade-off. If callers need to branch, the function belongs in a library and should use thiserror.
- The error message lacks detail
- No context was added. Attach .context() at each boundary describing what was being attempted.
Best practices
- Use anyhow in binaries and thiserror in libraries; do not expose anyhow in a public API.
- Add context at each layer — the chain is what makes production errors debuggable.
- Prefer with_context over context when the message needs formatting; it avoids the cost on success.
- Set RUST_BACKTRACE=1 to get a backtrace attached automatically.
Background
Why it exists, and what it was reacting to.
The companion to thiserror, also by David Tolnay. In an application you usually only want to report an error, not match on it — anyhow removes the boilerplate of enumerating every failure.
