serde_json::Error not implement std::error::Error

Hi,

I try to create my own error that keep the stacktrace. Here is the code :

fn from(content: Value) -> Result<Self, CustomError>
    where
        Self: Sized + for<'a> Deserialize<'a>,
{
        match from_value::<Self>(content) {
            Ok(value) => Ok(value),
            Err(error) => Err(CustomError::from(error)),
        }
}

#[derive(Debug, Clone, Default)]
pub struct CustomError {
    error_type: ErrorType, // enum
    cause: Option<Rc<dyn Error>>,
}

impl CustomError {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }
}

impl Error for CustomError {}

impl Display for CustomError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} {}", self.error_type, self.cause.as_ref().map(|c| format!("{}", c)).unwrap_or_default())
    }
}

impl From<ErrorType> for CustomError {
    fn from(error_type: ErrorType) -> Self {
        Self {
            error_type,
            ..Default::default()
        }
    }
}

impl From<Rc<dyn Error>> for CustomError {
    fn from(cause: Rc<dyn Error>) -> Self {
        Self {
            cause: Some(cause),
            ..Default::default()
        }
    }
}

But I can't put the serde_json::error into my custom error. I get the error :

error[E0277]: the trait bound `CustomError: From<serde_json::Error>` is not satisfied
  --> lib\src\domain\component.rs:13:31
   |
13 |             Err(error) => Err(CustomError::from(error)),
   |                               ^^^^^^^^^^^ the trait `From<serde_json::Error>` is not implemented for `CustomError`
   |
   = help: the following other types implement trait `From<T>`:
             <CustomError as From<ErrorType>>
             <CustomError as From<Rc<(dyn StdError + 'static)>>>

With some research, I found that the error is caused because serde_json error does not implement std.
But in the documentation, that is not wath they said : As long as there is a memory allocator, it is possible to use serde_json without the rest of the Rust standard library. Disable the default “std” feature and enable the “alloc” feature

So what did I misunderstood ?

Thanks in advance :slight_smile:

Since serde's Error does not implement the trait Error, you'll have to implement the conversion from Serde's Error to your custom error.

1 Like

Serde has some facade over the standard Error trait because Error was originally only available in std, then in core but only on unstable, and finally it will be available in core on unstable in the next Rust release.[1] I believe serde_json is implementing against that facade.

So presumably at some point after Error in core is available on stable, and whatever MSRV constraints have passed, the facade will become just a re-export and the standard Error trait will be implemented without the std or unstable features.


  1. or one after that, not sure when beta drops/dropped this cycle ↩︎

That doesn't seem like the right link (what does bytemuck have to do with this?)

Thanks, fixed.

Ok thank you all !

I was thinking that a good library must implement std::error::Error for custom errors, but it is not mandatory (too bad, it would have been a nice thing).

For who's who want the answer to my question, here's how I've handle this error like this (thanks to stackoverflow) :

impl From<serde_json::error::Error> for CustomError {
    fn from(cause: serde_json::error::Error) -> Self {
        Self {
            cause: Some(Rc::new(cause) as Rc<dyn Error>),
            ..Default::default()
        }
    }
}

The convenient thing to look for, when wondering when a stabilized feature will be released, is the version number that's the “milestone” of the the stabilization PR, which in this case is 1.81.0, which Forge tells us will be released on September 5.

This code has compiled successfully since the first Rust 1.0.0-alpha, in which std::error::Error first got added.

fn f<E: std::error::Error>() {}

fn main() {
    f::<serde_json::Error>();  // or serde::json::Error, in older versions
}
2 Likes

Hey,

So if I want to not define a custom from I have to use the nightly, that's right ?
If so, I will wait, I prefer to be on stable ^^'

Sorry, I do not understand your answer in relation to my needs.

Could you provide an example with the struct ? Or explain how to implement it in the given code ?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.