mcpField
M
m06-error-handling

m06-error-handling

github.com/actionbook开发1.6k3.5k 次安装9 周前更新
代码仓库

关于 m06-error-handling

面向 Rust 开发者的错误处理技能,帮助为库和应用设计失败处理方式。它区分预期失败与程序错误,并指导选择合适的类型、传播方式和上下文信息。

主要功能

  1. 01区分预期失败与程序错误
  2. 02选择 Result、Option 或 panic
  3. 03比较库和应用的错误处理模式
  4. 04传播错误时保留上下文

适用场景

  1. 01设计 API 的错误返回类型
  2. 02替换不安全的 unwrap 用法
  3. 03为传播的错误补充上下文

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/actionbook/rust-skills --skill m06-error-handling

安装后在 Claude Code 中输入/m06-error-handling确认已加载。

附带文件examples/library-vs-app.mdpatterns/error-patterns.md

详细介绍

错误处理

第 1 层:语言机制

核心问题

这是预期内的失败,还是 Bug?

在选择错误处理策略之前:

  • 这在正常运行中可能发生吗?
  • 谁应该处理这个失败?
  • 调用方需要哪些上下文?

错误 → 设计问题

模式不要只说应该问
unwrap 引发 panic“用 ?”这里真的可能是 None/Err 吗?
? 上的类型不匹配“用 anyhow”错误类型的设计是否合理?
错误上下文丢失“加上 .context()”调用方需要了解什么?
错误变体过多“用 Box”错误粒度是否合适?

思考提示

处理错误之前:

  1. 这是什么类型的失败?

    • 预期内 → Result<T, E>
    • 缺失是正常情况 → Option
    • Bug/不变量被破坏 → panic!
    • 不可恢复 → panic!
  2. 由谁处理?

    • 调用方 → 使用 ? 传播
    • 当前函数 → 使用 match/if-let
    • 用户 → 显示友好的错误消息
    • 程序员 → 使用消息触发 panic
  3. 需要哪些上下文?

    • 错误类型 → thiserror 变体
    • 调用链 → anyhow::Context
    • 调试信息 → anyhow 或 tracing

向上追溯 ↑

错误策略不明确时:

"Should I return Result or Option?"
    ↑ Ask: Is absence/failure normal or exceptional?
    ↑ Check: m09-domain (what does domain say?)
    ↑ Check: domain-* (error handling requirements)
情况追溯到问题
unwrap 过多m09-domain数据模型是否合理?
错误上下文设计m13-domain-error需要怎样的恢复方式?
库错误与应用错误m11-ecosystem谁会使用它们?

向下追溯 ↓

从设计到实现:

"Expected failure, library code"
    ↓ Use: thiserror for typed errors

"Expected failure, application code"
    ↓ Use: anyhow for ergonomic errors

"Absence is normal (find, get, lookup)"
    ↓ Use: Option<T>

"Bug or invariant violation"
    ↓ Use: panic!, assert!, unreachable!

"Need to propagate with context"
    ↓ Use: .context("what was happening")

快速参考

模式适用情况示例
Result<T, E>可恢复的错误fn read() -> Result<String, io::Error>
Option<T>缺失是正常情况fn find() -> Option<&Item>
?传播错误let data = file.read()?;
unwrap()仅用于开发/测试config.get("key").unwrap()
expect()不变量成立env.get("HOME").expect("HOME set")
panic!不可恢复panic!("critical failure")

库与应用程序

上下文错误 Crate原因
库thiserror为使用者提供有类型的错误
应用程序anyhow便捷的错误处理
混合两者在边界处使用 thiserror,内部使用 anyhow

决策流程图

Is failure expected?
├─ Yes → Is absence the only "failure"?
│        ├─ Yes → Option<T>
│        └─ No → Result<T, E>
│                 ├─ Library → thiserror
│                 └─ Application → anyhow
└─ No → Is it a bug?
        ├─ Yes → panic!, assert!
        └─ No → Consider if really unrecoverable

Use ? → Need context?
├─ Yes → .context("message")
└─ No → Plain ?

常见错误

错误原因修复方法
unwrap() panic未处理 None/Err使用 ? 或 match
类型不匹配错误类型不同使用 anyhow 或 From
上下文丢失? 未附加上下文添加 .context()
cannot use ?缺少 Result 返回类型返回 Result<(), E>

反模式

反模式不妥之处更好的做法
到处使用 .unwrap()在生产环境中触发 panic使用 .expect("reason") 或 ?
默默忽略错误隐藏 Bug处理错误或传播错误
对预期内的错误使用 panic!用户体验差,无法恢复使用 Result
到处使用 Box类型信息丢失使用 thiserror

相关技能

适用情况参见
领域错误策略m13-domain-error
Crate 边界m11-ecosystem
类型安全的错误m05-type-driven
心智模型m14-mental-model

评论

支持 Markdown