Rust Error Handling Compared: anyhow vs thiserror vs snafu
Error handling is an indispensable part of Rust development. Rust’s Result provides fundamental support, but the specific implementation varies depending on the scenario. This article introduces three commonly used error handling tools—anyhow, thiserror, and snafu—analyzing their characteristics and applicable scenarios, and helps you understand through practical examples how to use them in projects. Whether you are developing applications or writing libraries, this article can serve as a valuable reference. This article delves deeply into the three major tools for Rust error handling: anyhow is suitable for rapid and unified error handling, ideal for application development; thiserror supports customized error types, making it suitable for library development; snafu provides context-driven error management, appropriate for complex systems. Through comparing their strengths and weaknesses and demonstrating actual code examples, we will show you how to choose the right tool based on project needs. We also provide project setup steps and example code to help you handle errors more effectively in Rust. Rust Error Handling Error Handling: anyhow, thiserror, snafu anyhow: unified and simple error handling, suitable for application-level programming thiserror: customized and rich error handling, suitable for library-level programming snafu: finer-grained error management Note: When developing, pay attention to the size of Result. anyhow Error: Application-level Error Handling Conversion and unified error handling with anyhow::Error: Provides a unified anyhow::Error type, supporting any error type that implements std::error::Error Uses the ? operator for automatic error propagation, simplifying multi-layer nested error handling Supports adding dynamic context (via the context() method) to enhance error readability fn get_cluster_info() -> Result { // Error 3: Err3 let config = std::fs::read_to_string("cluster.json")?; // Error 1: Err1 // let config = std::fs::read_to_string("cluster.json").context("...")?; // Error 1: Err1 let map: ClusterMap = serde_json::from_str(&config)?; // Error 2: Err2 Ok(map) } struct Err1 {...} struct Err2 {...} match ret { Ok(v) => v, Err(e) => return Err(e.into()) } Err1 => Err3: impl From for Err3 Err2 => Err3: impl From for Err3 impl From for Err3 { fn from(v: Err1) -> Err3 { ... } } thiserror Error: Defining Library-level Errors Automatically generates error types that conform to std::error::Error via macros Supports nested error sources (using the #[from] attribute) and structured error information Allows customization of error message templates (e.g., #[error("Invalid header: {expected}")]) Reference: Rust std::error::Error trait documentation Since the Error trait requires implementing both Debug and Display: pub trait Error: Debug + Display { It can be printed like this: Error -> println!("{}/ {:?}", err) snafu Error: Context-driven Error Management Converts underlying errors into domain-specific errors through the Snafu macro Supports attaching structured context (such as file paths, input parameters) in the error chain Provides the ensure! macro to simplify condition checking and error throwing thiserror vs snafu For more information, refer to: kube-rs/kube discussion #453 Comparison and Selection Guide Dimension anyhow thiserror snafu Error Type Unified dynamic type Static custom type Domain-driven type Context Support Dynamic string Struct fields Structured fields + dynamic templates Suitable Stage Application development (rapid iteration) Library development (stable interfaces) Complex systems (maintainability) Learning Curve Low (no need to predefine types) Medium (requires designing error structures) High (requires understanding context models) Typical Users Frontend developers / scripting tool developers Framework developers Infrastructure engineers Practical Implementation Create and Initialize Project rust-ecosystem-learning Based on a Template cargo generate --git git@github.com:qiaopengjun5162/rust-template.git cd rust-ecosystem-learning code . Project Directory Structure rust-ecosystem-learning on main [!] is

Error handling is an indispensable part of Rust development. Rust’s Result
provides fundamental support, but the specific implementation varies depending on the scenario. This article introduces three commonly used error handling tools—anyhow
, thiserror
, and snafu
—analyzing their characteristics and applicable scenarios, and helps you understand through practical examples how to use them in projects. Whether you are developing applications or writing libraries, this article can serve as a valuable reference.
This article delves deeply into the three major tools for Rust error handling:
-
anyhow
is suitable for rapid and unified error handling, ideal for application development; -
thiserror
supports customized error types, making it suitable for library development; -
snafu
provides context-driven error management, appropriate for complex systems.
Through comparing their strengths and weaknesses and demonstrating actual code examples, we will show you how to choose the right tool based on project needs. We also provide project setup steps and example code to help you handle errors more effectively in Rust.
Rust Error Handling
Error Handling: anyhow
, thiserror
, snafu
-
anyhow
: unified and simple error handling, suitable for application-level programming -
thiserror
: customized and rich error handling, suitable for library-level programming -
snafu
: finer-grained error management
Note: When developing, pay attention to the size of Result
.
anyhow
Error: Application-level Error Handling
Conversion and unified error handling with anyhow::Error
:
- Provides a unified
anyhow::Error
type, supporting any error type that implementsstd::error::Error
- Uses the
?
operator for automatic error propagation, simplifying multi-layer nested error handling - Supports adding dynamic context (via the
context()
method) to enhance error readability
fn get_cluster_info() -> Result<ClusterMap, anyhow::Error> { // Error 3: Err3
let config = std::fs::read_to_string("cluster.json")?; // Error 1: Err1
// let config = std::fs::read_to_string("cluster.json").context("...")?; // Error 1: Err1
let map: ClusterMap = serde_json::from_str(&config)?; // Error 2: Err2
Ok(map)
}
struct Err1 {...}
struct Err2 {...}
match ret {
Ok(v) => v,
Err(e) => return Err(e.into())
}
Err1 => Err3: impl From<Err1> for Err3
Err2 => Err3: impl From<Err2> for Err3
impl From<Err1> for Err3 {
fn from(v: Err1) -> Err3 {
...
}
}
thiserror
Error: Defining Library-level Errors
- Automatically generates error types that conform to
std::error::Error
via macros - Supports nested error sources (using the
#[from]
attribute) and structured error information - Allows customization of error message templates (e.g.,
#[error("Invalid header: {expected}")]
)
Reference: Rust std::error::Error trait documentation
Since the Error
trait requires implementing both Debug
and Display
:
pub trait Error: Debug + Display {
It can be printed like this:
Error -> println!("{}/ {:?}", err)
snafu
Error: Context-driven Error Management
- Converts underlying errors into domain-specific errors through the
Snafu
macro - Supports attaching structured context (such as file paths, input parameters) in the error chain
- Provides the
ensure!
macro to simplify condition checking and error throwing
thiserror
vs snafu
For more information, refer to: kube-rs/kube discussion #453
Comparison and Selection Guide
Dimension | anyhow | thiserror | snafu |
---|---|---|---|
Error Type | Unified dynamic type | Static custom type | Domain-driven type |
Context Support | Dynamic string | Struct fields | Structured fields + dynamic templates |
Suitable Stage | Application development (rapid iteration) | Library development (stable interfaces) | Complex systems (maintainability) |
Learning Curve | Low (no need to predefine types) | Medium (requires designing error structures) | High (requires understanding context models) |
Typical Users | Frontend developers / scripting tool developers | Framework developers | Infrastructure engineers |
Practical Implementation
Create and Initialize Project rust-ecosystem-learning
Based on a Template
cargo generate --git git@github.com:qiaopengjun5162/rust-template.git
cd rust-ecosystem-learning
code .
Project Directory Structure
rust-ecosystem-learning on main [!] is