Why serde_json::Error can not be linked in chain_error?


#1

The following code does not have issues with Hyper, but reports "failed to resolve. Did you mean adapter::serde_json" for Serde

error_chain! {
    foreign_links {
        Hyper(::hyper::Error);
        Serde(::serde_json::Error);
    }
}

Why is this? How can I fix it?


#2

Well, it turned out that foreign_links is not needed for serde_json because serde_json::Error converts to errors::Error from error_chain with following up chain_err() call without foreign_links declaration. This is good, but I do not understand why it works this way for serde_json and does not work for hyper (where it still requires foreign_links declaration)?


#3

Can you post a working example? I needed to use foreign_links.


#4

This is what I ended up with. And serde errors can be still chained with chain_err(). I do not know why it works and could not explain it myself.

error_chain! {
    foreign_links {
        Hyper(::hyper::Error);
    }
}

#5

What’s the error when you try to chain a hyper error (without a foreign link to it)?


#6

Hmm… I tried now without this section and it compiles. Before it did not and adding foreign_links helped. Now I am totally confused how 3rd party error can be converted to my error type without doing anything special. Could you please explain?


#7

Can you show the full code where you define the errors and your chain_err call?


#8

Here is my error chain definition (foreign_links section was not commented out before I attempted to answer your previous question):

error_chain! {
    errors {
        NegativeResponse(status: ::hyper::StatusCode, body: String) {
            display("unexpected negative response: {}, {}", status, body)
        }
    }

//    foreign_links {
//        Hyper(::hyper::Error);
//    }
}

Few examples of usages are below:

let point: Point = serde_json::from_str(&req_body).chain_err(|| "parsing JSON request")?;
...
let mut core: Core = Core::new().chain_err(|| "creating event loop reactor")?;
...
let listener: TcpListener = TcpListener::bind(&address, &handle).chain_err(|| format!("binding to {}", address))?;
...
fn send_request(&self, req: &mut RequestBuilder) -> Box<Future<Item=Response, Error=errors::Error>> {
        Box::new(req.send().then(|r| {
            let response: Response = r.chain_err(|| "sending http request")?;
            Ok(response)
        }))
    }

I guess I know why removal of foreign_link for hyper did not trigger compiler error as it did before :slight_smile: It is because I migrated from using hyper client to reqwest client few days ago. Anyway, reqwest and serde_json have got custom result types, which are somehow chained without declaration of foreign links…


#9

So you’re calling chain_err with a closure yielding a String or a string slice - that’s supported out of the box because the generated ErrorKind has From impls for both of those types.


#10

Does it mean that I would need foreign_links for Hyper Error, if I had something like the following:?

let response: Response = r.chain_err(|| { Hyper::Error(...) })?;

#11

I guess I had something like this before I ended up chaining with strings:

let point: Point = serde_json::from_str(&req_body)?;

This triggered compiler error like:

71 |             let point: Point = serde_json::from_str(&req_body)?;
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<server::serde_json::Error>` is not implemented for `errors::Error`
   |
   = help: the following implementations were found:
             <errors::Error as std::convert::From<errors::ErrorKind>>
             <errors::Error as std::convert::From<&'a str>>
             <errors::Error as std::convert::From<std::string::String>>
   = note: required by `std::convert::From::from`

I guess this is when foreign_link is required now for serde_json::Error type…?


#12

Yeah, that’s right.


#13

Thanks


#14

I don’t know whether it is appropriate to up the old post, but I have the exact same error with the serde_json and hyper. How can I convert one error to another, if I’m using the failure crate? Now I have to use .expect(...) but I want avoid panics.


#15

Better to start a new thread with details specific to your case. You can link to this thread there if you think it adds useful context.