When using a custom type and #[serde(try_from = "..."], errors that the try_from call throws are not forwarded correctly. Instead, they are converted into strings with no control about how the conversion behaves, and the original error is dropped instead of saving it as a source. This means that the actual error that caused the deserialization to fail will be forgotten if it is wrapped in some context management.
Example code:
use anyhow::{Context, anyhow};
use serde_derive::Deserialize;
#[derive(Deserialize, Debug)]
#[serde(try_from = "u8", into = "u8")]
enum MyType {
Alpha, Bravo, Charlie
}
impl TryFrom<u8> for MyType {
type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
number_to_my_type(value)
}
}
fn number_to_my_type(number: u8) -> Result<MyType, anyhow::Error> {
// this is the only error which will be printed
number_to_my_type_inner(number).context("number to my type: Outer function")
}
fn number_to_my_type_inner(number: u8) -> Result<MyType, anyhow::Error> {
match number {
67 => Ok(MyType::Alpha),
68 => Ok(MyType::Bravo),
69 => Ok(MyType::Charlie),
// but I want to see this important error message
num => Err(anyhow!("IMPORTANT ERROR MESSAGE: {num} was an invalid number"))
}
}
fn parse_json() -> Result<MyType, anyhow::Error> {
serde_json::from_str("128")
// at this point, a serde_json Error is returned, which is created by calling custom() I guess
// the problem is that custom() takes a variable of type Into<String>, so the only thing serde_json can do with it
// is to convert it to a string, but it can't save any important information about the error
.context("Parsing a string")
}
fn main() {
let x = parse_json().expect("error");
println!("{x:?}");
}
This code prints
thread 'main' (119114) panicked at src/main.rs:36:26:
error: Parsing a string
Caused by:
number to my type: Outer function
When using a custom type and
#[serde(try_from = "..."], errors that thetry_fromcall throws are not forwarded correctly. Instead, they are converted into strings with no control about how the conversion behaves, and the original error is dropped instead of saving it as a source. This means that the actual error that caused the deserialization to fail will be forgotten if it is wrapped in some context management.Example code:
This code prints