`Result<T, E>` chains like `Option`. The `?` operator unwraps `Ok` or early-returns the `Err`, converting via `From` so callers can use one error type for many sources.
Encode "this might fail" in the type signature instead of throwing. Force the caller to handle both branches at compile time. Better than try/catch for foreseeable failures.
If you don't want the thiserror/anyhow dependency, `Box<dyn std::error::Error>` works as a catch-all. The `?` operator promotes any concrete error via `From`.
`anyhow::Result<T>` is `Result<T, anyhow::Error>` — a type-erased error that captures any other error AND adds context via `.context()`. The app-author's pick (use thiserror for libraries).
The `thiserror` crate generates a clean `Error + Display + Debug` impl from an enum, with automatic `From` conversions. The library-author's error-type tool of choice.