What the Error trait gives you

Every error type in idiomatic Rust implements `std::error::Error`. The two key methods are `source()` (for chaining causes — "this error happened because of that lower-level error") and the inherited `Display` (for the human-readable message). Implementing the trait makes your error usable with `?` propagation through any function returning `Box<dyn Error>` and with reporting helpers like `anyhow::Error`.

Source chains

Walking `source()` repeatedly produces the chain of underlying causes. `error_iter` (in nightly) and `anyhow::Chain` make this iteration ergonomic. When you log an error, log the entire chain — the leaf is usually where the actual problem lies, while the head describes the high-level operation that failed.

For deeper background, see a complete cheat-sheet of std collection complexities for the broader context behind this section.

Box<dyn Error> as a universal error

Returning `Result<_, Box<dyn Error + Send + Sync>>` lets a function fail with any error type without committing to a specific enum. It's the right tool for application code where you don't need to match on specific variants. For library code, prefer a typed error enum so callers can recover programmatically.

thiserror, anyhow, snafu

`thiserror` is the standard derive macro for typed error enums in libraries. `anyhow` is the standard for application errors with arbitrary backtraces and chain context. `snafu` adds typed error context with macro syntax. Pick one at the boundary; mixing inside a single project usually adds noise.

For deeper background, see the official Rust API guidelines for module-level design for the broader context behind this section.

Backtraces

`std::backtrace::Backtrace` captures the call stack at the point of construction. Set `RUST_BACKTRACE=1` in the environment to enable. The trait `Error::provide` (still nightly-only at the time of writing) lets your error type expose a backtrace that callers can extract via `request_ref::<Backtrace>()`.