thiserror组合anyhow处理异常时缺少context信息的问题 2025-05-12 00:28:41 ## 背景 最近在用rust处理一个项目,其中用到了anyhow简化异常处理,使用anyhow的context能力,对异常做了包装,同时用thiserror又对anyhow的Error封装了一层。 大概是类似这样的处理代码。 业务中: ```rust use anyhow::{Result, Context}; ... // 创建文件 let mut file = File::create(path) .await .context(format!("无法创建文件: {}", save_path))?; ``` 使用thiserror的二次封装: ```rust #[derive(thiserror::Error, Debug)] pub enum Error { #[error("{0}")] Error(String), #[error(transparent)] AnyHow(#[from] anyhow::Error), } ``` 结果出现异常后,缺少了上下文信息(也就是context的root cause信息),输出的异常是这样的: ``` 无法创建文件: D:/xxxx/files/zGT4eek9_%E5%89%AF%E6%9C%AC%E5%9B%BD%E7%BD%91%E6%B2%83%E5%8D%97%E4%BF%A1%E9%80%9A%E5%85%AC%E5%8F%B8%E3%80%8C%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%8D%81%E5%85%AB%E8%88%AC%E6%AD%A6%E8%89%BA%E3%80%BD%E5%85%68%E5%9E%86%E5%8A%94%E7%94%48%E9%98%86%E9%94%A6-1029.png ``` 这样就无法看到背后的真实出错信息了。 ## 分析 看anyhow的文档对context的描述应该是可以自动附带异常信息的,所以又深入了解了下文档的介绍: <https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations> 发现输出格式跟Display representations有关,将anyhow的error对象使用 “{}” 或 to_string()输出时,只有context的异常信息,没有背后的异常信息,也就是这个原因导致了root cause丢失了。 可以通过:`{:#}或{:?}`展现root cause的内容。 ## 解决 如果直接输出anyhow的异常,类似下面这样: ``` match your_func().await { Ok(data) => println!("data: {}", data), Err(e) => eprintln!("error: {:#}", e), } ``` 就可以直接按我们期望的方式看到详细的异常信息了。 但通过thiserror封装的话就需要额外处理了,我们可以额外为Error添加一个序列化方法,最终代码如下: ```rust #[derive(thiserror::Error, Debug)] pub enum Error { #[error("{0}")] Error(String), #[error(transparent)] AnyHow(#[from] anyhow::Error), } impl serde::Serialize for Error { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::ser::Serializer, { serializer.serialize_str(format!("{:#}", self).as_ref()) } } ``` 这样,再出异常的话就可以看到类似这样的输出了: ``` 无法创建文件: D:/xxxx/files/zGT4eek9_%E5%89%AF%E6%9C%AC%E5%9B%BD%E7%BD%91%E6%B2%83%E5%8D%97%E4%BF%A1%E9%80%9A%E5%85%AC%E5%8F%B8%E3%80%8C%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%8D%81%E5%85%AB%E8%88%AC%E6%AD%A6%E8%89%BA%E3%80%BD%E5%85%68%E5%9E%86%E5%8A%94%E7%94%48%E9%98%86%E9%94%A6-1029.png: 文件名、目录名或卷标语法不正确。 (os error 123) ``` 既有业务上能够看得懂的异常描述,又有导致异常的具体信息,完美~ 非特殊说明,均为原创,原创文章,未经允许谢绝转载。 原始链接:thiserror组合anyhow处理异常时缺少context信息的问题 赏 Next Reqable代理API抓包调试应用注意点