You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Risks of Type-Erased Error Handling: eyre and anyhow
eyre and anyhow are popular Rust libraries designed to simplify error handling by boxing diverse error types into a single, opaque wrapper (e.g., eyre::Report or anyhow::Error). While convenient, this approach allows any type implementing the std::error::Error trait to be captured, effectively erasing specific type information.
The Architectural "Smell"
Using these libraries across an entire codebase is often considered a modern evolution of CWE-396: Declaration of Catch-for-All. It mirrors the Java anti-pattern of adding throws Exception to every method signature, leading to several critical issues:
Implementation Leaks: Internal implementation details are obscured rather than properly abstracted.
Implicit Coupling: The caller becomes implicitly dependent on the internal error types of the callee without a formal contract.
Loss of Exhaustiveness: Because the error is a "catch-all," the compiler can no longer ensure you have handled all possible error variants.
Bypassing the Compiler
The primary danger lies in how these errors are consumed. If a call-site needs to react to a specific error, it must perform a runtime downcast (using downcast_ref).
The Risk: Runtime downcasting bypasses Rust’s core strength: compile-time safety.
If the underlying implementation changes its error types, the call-site code will still compile perfectly, but the downcasting logic will silently fail at runtime. This introduces "invisible" breaking changes, leading to logic bugs and potential security vulnerabilities where error-handling paths are unintentionally skipped.
Proposed solution
Stop using eyere/anyhow and create specific error type that implements the standard Error trait to make them composable.
Using thiserror crates helps to follow the standard lib error trait convention.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The Risks of Type-Erased Error Handling: eyre and anyhow
eyre and anyhow are popular Rust libraries designed to simplify error handling by boxing diverse error types into a single, opaque wrapper (e.g., eyre::Report or anyhow::Error). While convenient, this approach allows any type implementing the std::error::Error trait to be captured, effectively erasing specific type information.
The Architectural "Smell"
Using these libraries across an entire codebase is often considered a modern evolution of CWE-396: Declaration of Catch-for-All. It mirrors the Java anti-pattern of adding throws Exception to every method signature, leading to several critical issues:
Implementation Leaks: Internal implementation details are obscured rather than properly abstracted.
Implicit Coupling: The caller becomes implicitly dependent on the internal error types of the callee without a formal contract.
Loss of Exhaustiveness: Because the error is a "catch-all," the compiler can no longer ensure you have handled all possible error variants.
Bypassing the Compiler
The primary danger lies in how these errors are consumed. If a call-site needs to react to a specific error, it must perform a runtime downcast (using downcast_ref).
The Risk: Runtime downcasting bypasses Rust’s core strength: compile-time safety.
If the underlying implementation changes its error types, the call-site code will still compile perfectly, but the downcasting logic will silently fail at runtime. This introduces "invisible" breaking changes, leading to logic bugs and potential security vulnerabilities where error-handling paths are unintentionally skipped.
Proposed solution
Stop using eyere/anyhow and create specific error type that implements the standard Error trait to make them composable.
Using
thiserrorcrates helps to follow the standard lib error trait convention.All reactions