When implementing error handling, balance between propagation and recovery. Design error types to preserve context while providing users with meaningful ways to handle failure.
When implementing error handling, balance between propagation and recovery. Design error types to preserve context while providing users with meaningful ways to handle failure.
For error propagation:
std::error::Error
trait, including source()
method for error chainingResult<usize>
over Result<()>
when position information is needed)Send + Sync
error types when errors might cross thread boundariesFor recovery paths:
// Poor: May panic unexpectedly and loses context
let pos = std.stream_position().unwrap();
// Better: Provides fallback and preserves error context
let pos = std.stream_position().unwrap_or(0);
// Poor: Error type lacks context and proper trait implementation
struct MyError(());
// Better: Full featured error with context preservation
struct MyError<T> {
inner: T,
cause: io::Error,
}
impl<T> std::error::Error for MyError<T> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.cause)
}
}
// Even in examples, show proper error handling
// Poor: Ignores errors
let _ = compress_data(reader).await;
// Better: Shows proper error handling
compress_data(reader).await?;
Enter the URL of a public GitHub repository