Error Context & Backtraces
Attach context as errors bubble up. Enable backtraces (RUST_BACKTRACE=1) for panic and some error types to locate failure origins.
Recipe
use anyhow::Context;
fn load(path: &str) -> anyhow::Result<String> {
std::fs::read_to_string(path)
.with_context(|| format!("failed to read config at {path}"))
}When to reach for this: Production debugging - know what operation failed, not only low-level cause.
Working Example
fn pipeline(cfg_path: &str) -> anyhow::Result<u16> {
let raw = load(cfg_path)?;
let port: u16 = raw.trim().parse().context("port must be integer")?;
Ok(port)
}
fn main() {
if let Err(e) = pipeline("missing.toml") {
eprintln!("Error: {e:#}");
for cause in e.chain() {
eprintln!(" caused by: {cause}");
}
}
}What this demonstrates:
- Layered context messages
{e:#}alternate display with causes- Chain iteration for logs
Deep Dive
std::backtrace::Backtrace capture on nightly/stable features varies - RUST_BACKTRACE=1 for panics. anyhow backtrace feature adds to errors.
Gotchas
- Context without actionable info - "failed" useless. Fix: Include paths, ids, operation names.
- Logging same error multiple layers - Duplicate noise. Fix: Log once at boundary with chain.
- Backtrace in hot path - Expensive capture. Fix: Capture on error only, not success.
- Secrets in context - Tokens in paths. Fix: Redact sensitive fields.
- thiserror without source - Broken chain. Fix:
#[source]attribute on variants.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Structured tracing | Production observability | Simple CLI |
snafu context | Typed contexts | anyhow simplicity |
| Manual match logging | Full control | Verbose |
FAQs
RUST_BACKTRACE values?
1 full, limited variants per docs.Panic backtrace?
Always available with env var.Error backtrace anyhow?
Feature flag required.tracing error!
Log `%?` debug or display chain.serde context?
Separate from serde parse errors.#[source] thiserror?
Links variant to inner error.Context on Option?
Use `ok_or_else` with context before ?.CI backtraces?
Enable on test failures for flakes.wasm backtrace?
Limited platform support.Security?
Do not expose internal paths to users - map at HTTP layer.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.