More ergonomic wrapper for repeated map_err() with custom message

⚓ Rust    📅 2026-05-27    👤 surdeus    👁️ 2      

surdeus

I have an enum called TmrConnectError set up using thiserror:

#[derive(Debug, thiserror::Error)]
pub enum TmrConnectError {
    #[error("Authentication failed: {msg}")]
    AuthError {
        msg: String,
        source: Option<Box<dyn std::error::Error + Send + Sync>>,
    },

I often map_err rmcp::transport::AuthError into this error (14 places), but I also have some places without that error as the source.

I wanted to do the creating of the error more ergonomic, so I first thought about #[from] and impl From<rmcp::transport::AuthError> for TmrConnectError, but I realized that #[from] does not support leaving out the rmcp error and that I can not provide my own informative message.

So instead, I have created a trait to hook a function function onto the rmcp error.

Does this look like a nice solution to you? Are there nicer alternatives?

Original call-site:

oauth_state
    .handle_callback(&auth_code, &csrf_token)
    .await
    .map_err(|e| TmrConnectError::AuthError {
        msg: "Failed to handle authorization callback".to_string(),
        source: Some(e.into()),
    })?;

Trait:

pub(crate) trait MapAuthToConnectError<T> {
    fn to_connect_err(self, msg: impl Into<String>) -> Result<T, TmrConnectError>;
}

impl<T> MapAuthToConnectError<T> for Result<T, rmcp::transport::AuthError> {
    fn to_connect_err(self, msg: impl Into<String>) -> Result<T, TmrConnectError> {
        self.map_err(|e| TmrConnectError::AuthError {
            msg: msg.into(),
            source: Some(Box::new(e)),
        })
    }
}

Updated call-site:

oauth_state
    .handle_callback(&auth_code, &csrf_token)
    .await
    .to_connect_err("Failed to handle authorization callback")?;

I just realized that I could also do a free-standing function, but I think it will look more messy at the call-site:

fn to_connect_err(auth_err: rmcp::transport::AuthError, msg: impl Into<String>) -> Result<T, TmrConnectError>;

edit: I just realized that I might want to append the inner error message to the outer one. Should be possible to do in my function.

2 posts - 2 participants

Read full topic

🏷️ Rust_feed