On this page
Error Trait and Ecosystem
std::error::Erroris merely a combination ofDisplay + Debug + source()—it is too thin.thiserroruses derive macros to generate structured error types for libraries (allowing callers to match), whileanyhowprovides a universal error wrapper for applications that "doesn't care about the error type, just propagates it upward." Libraries usethiserror, applications useanyhow—this is not dogma, but a division of labor refined through practice.
std::error::Error trait
The standard library's Error trait is simple—Display + Debug + source():
use Error;
use fmt;
The source() method returns the underlying cause, forming an error chain. anyhow and eyre leverage this chain to automatically generate backtraces.
thiserror: derive macro for library crates
Used for libraries—providing concrete, matchable error types to callers:
use Error;
#[from] automatically generates From<io::Error> for DataStoreError, allowing the ? operator to perform automatic conversion. Callers can use match to distinguish error types.
anyhow: generic error container for application code
Used for applications/binaries—collecting error chains without caring about specific types:
use ;
anyhow::Error can store any Error + Send + Sync + 'static. context() adds human-readable comments to the error chain—this is the most common pattern in anyhow.
When to use thiserror vs anyhow
A simple rule: Libraries use thiserror (giving callers choice), applications use anyhow (collecting error context). Libraries should not force callers to use a specific error reporting library—throw concrete, matchable types. Applications do not need to distinguish error types—they need all errors to be caught, logged, and have sufficient context to reproduce bugs.
References
- thiserror: docs.rs/thiserror
- anyhow: docs.rs/anyhow
Keywords: Error trait, thiserror, anyhow, context, source, error chain, #[from]