TL;DR
A Rust developer outlines a method for building error types using only the standard library, avoiding popular crates like anyhow, thiserror and eyre. The piece shows how to add location and contextual input data to errors with #[track_caller], Location::caller, and map_err, while noting trade-offs in verbosity and ergonomics.
What happened
The author presented a practical approach to Rust error handling that relies solely on the standard library rather than external error crates. They walk through progressively richer examples: starting with a simple Error-implementing enum wrapping ParseIntError; then adding a struct that captures call-site location using #[track_caller] and Location::caller; and finally showing how to attach contextual strings for failed inputs by creating a DemoError::new and converting parse failures with map_err. The write-up contrasts this pattern with common third-party libraries and with exception-based error handling in languages like JavaScript/Node.js, arguing for fewer dependencies for supply-chain and auditability reasons. The author acknowledges this is a personal style — not necessarily the single idiomatic path — and calls out trade-offs such as extra verbosity and more frequent map_err usage.
Why it matters
- Reducing third-party crates can lower supply-chain exposure and keeps more code under project control, per the author's rationale.
- Using std-only patterns still allows attaching useful diagnostic details (call-site location and failed input) to errors without external helpers.
- Explicit error construction enforces handling at the point of failure, aligning with Rust’s preference for composable return-value error handling over exceptions.
- The approach can help make failures more actionable in debugging and support finer-grained handling by callers.
Key facts
- The author prefers using the standard library to define error types rather than adding crates like anyhow, thiserror, or eyre.
- Examples demonstrate wrapping std::num::ParseIntError in a custom error enum and then evolving to a struct that stores Location::caller.
- #[track_caller] is used on conversion functions to capture the call-site location for improved error messages.
- Context about failed inputs is added by creating a DemoError::new and converting parse errors with .map_err to include the offending string.
- The resulting error messages in examples include both the parse failure description and the file:line:column location.
- The author notes that eliminating unwrap/expect universally is not always necessary; unwrap is acceptable when an error is truly impossible and assumptions are iron‑clad.
- A real-world incident is cited where an unwrap on a config file contributed to a Cloudflare outage, illustrating the risks of unchecked unwraps.
- The author warns that std-only error handling can produce verbose code littered with .map_err calls, and that the developer must balance verbosity against usefulness.
What to watch next
- Extra verbosity: frequent .map_err and manual error construction can make code more wordy and harder to scan.
- Using #[track_caller] and Location::caller improves diagnostics but requires deliberate placement on conversion/new functions.
- Potential misuse of unwrap/expect remains a hazard — correct use requires strong guarantees about inputs and invariants.
- not confirmed in the source
Quick glossary
- Result<T, E>: Rust’s standard enum for operations that can succeed (Ok) or fail (Err); promotes explicit handling of errors.
- unwrap / expect: Methods that extract the Ok value from a Result, panicking if it is an Err; intended for cases where an error is assumed impossible.
- map_err: A method on Result that transforms the Err variant with a provided function, commonly used to attach context or convert error types.
- #[track_caller] / Location::caller: Attributes and APIs in std that let a function record the source location (file, line, column) of its caller for improved diagnostics.
Reader FAQ
Is the std-only approach the idiomatic Rust way to write errors?
The author says this is their personal approach and not necessarily the single idiomatic standard; many Rust projects use crates like anyhow or thiserror.
Can you get contextual messages like anyhow::context without external crates?
Yes — the article shows adding context by constructing custom errors and using .map_err to include input strings and other context.
Will using std-only errors eliminate supply-chain risk?
The author argues it reduces third-party code surface and dependency exposure, but broader security implications are not fully detailed in the source.
Does this approach prevent panics caused by unwrap?
Not inherently; the piece stresses careful use of unwrap and shows alternatives, but it does not claim it will eliminate all unwrap-related panics.
Rust Errors Without Dependencies December 27th 2025 Rust error handling is a complex topic mostly due to the composability it gives you and no "blessed way" to accomplish this from…
Sources
- Rust errors without dependencies
- introducing a new error crate – announcements
- Why can a no_std crate depend on a crate that uses std?
- Error Handling for Large Rust Projects — A Deep Dive into
Related posts
- No, it’s not a battleship — proposed ‘Trump’ warship resembles a large missile cruiser
- Victor LaValle’s subversive cosmic-horror novella The Ballad of Black Tom
- Engineered ‘Beige’ Fat Cells May Starve Tumors by Outcompeting Them