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

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?

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)?

1 Like

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

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);
    }
}
1 Like

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

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?

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

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....

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.

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(...) })?;

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...?

Yeah, that’s right.

Thanks

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.

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.

2 Likes