More ergonomic wrapper for repeated map_err() with custom message
⚓ Rust 📅 2026-05-27 👤 surdeus 👁️ 2I 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
🏷️ Rust_feed