Why these errors are not automagically converted to my custom error even if they are implementing both `std::error::Error` trait?

Reproduction project (single main.rs file): GitHub - frederikhors/iss-custom-err.

I'm trying to create a custom error for my app:

pub struct AppError {
    message: String,
    error: anyhow::Error, // In the future I would also avoid anyhow
}

I'm trying to use it in my code but as you can see I'm getting the below compiler errors, why?

Isn't my AppError implementing the trait std::error::Error correctly?

I would expect an auto conversion from hyper error to AppError being both error:Error traits, am I wrong?

error[E0277]: `?` couldn't convert the error to `AppError`
  --> src\main.rs:20:44
   |
20 |                     .body(Body::from(body))?;
   |                                            ^ the trait `From<hyper::http::Error>` is not implemented for `AppError`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `FromResidual<R>`:
             <Result<T, F> as FromResidual<Result<Infallible, E>>>
             <Result<T, F> as FromResidual<Yeet<E>>>
   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, hyper::http::Error>>` for `Result<(), AppError>`

error[E0277]: `?` couldn't convert the error to `AppError`
  --> src\main.rs:24:19
   |
24 |             .await?;
   |                   ^ the trait `From<hyper::Error>` is not implemented for `AppError`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `FromResidual<R>`:
             <Result<T, F> as FromResidual<Result<Infallible, E>>>
             <Result<T, F> as FromResidual<Yeet<E>>>
   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, hyper::Error>>` for `Result<(), AppError>`

For more information about this error, try `rustc --explain E0277`.

SO answer: rust - Why these errors are not automagically converted to my custom error even if they are implementing both std::error::Error trait? - Stack Overflow

On discord a kind user helped me understand.

What I need is a generic impl:

impl<T: error::Error + Send + Sync + 'static> From<T> for AppError {
    fn from(e: T) -> Self {
        Self { message: e.to_string(), error: anyhow::Error::new(e) }
    }
}

That's it!

The reason this issue occurs is becaus the ? operator trait is completely unrelated to the std::error::Error trait. It does the conversion using From (Rust's generic conversion trait), which is why that snippet works - you provided a way to convert any T: std::error::Error into an AppError.

1 Like