Source in thiserror default display

I use AWS step functions to report errors and they need the full error message, including source details.

So how can I shove the source() into the default displayed error? Could it be as simple as?:

#[derive(Error, Debug)]
pub enum MyError {
    #[error("Reqwest failed: {0:?} caused by: {:?}", self.0.source())]
    ReqwestError(#[from] reqwest::Error)
}

I really would prefer to stay using thiserror and not anyhow

This works:

use std::error::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error("Reqwest failed: {0:?} caused by: {:?}", Error::source(.0))]
    ReqwestError(#[from] reqwest::Error),
}

But it's usually better to format errors with Display instead of Debug, so what you really want is something like:

use std::error::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error("Reqwest failed: {0} caused by: {}", Error::source(.0))]
    ReqwestError(#[from] reqwest::Error),
}

Except Option can't be formatted with Display, so you could do:

use std::error::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error("Reqwest failed: {0}{}", Error::source(.0).map(|e| format!(" caused by: {e}")).unwrap_or_default())]
    ReqwestError(#[from] reqwest::Error),
}

If it gets more complicated than this, I'd make another error type, implement traits for that type, and then use #[error(transparent)].

use std::error::Error;
use std::fmt::Display;

use thiserror::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error(transparent)]
    ReqwestError(#[from] ReqwestError),
}

#[derive(Debug)]
pub struct ReqwestError(reqwest::Error);

impl Display for ReqwestError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Reqwest failed: {}", self.0)?;

        if let Some(source) = self.source() {
            write!(f, " caused by: {source}")?;
        }

        Ok(())
    }
}

impl Error for ReqwestError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.0.source()
    }
}

impl From<reqwest::Error> for MyError {
    fn from(value: reqwest::Error) -> Self {
        Self::ReqwestError(ReqwestError(value))
    }
}
1 Like

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.