M06 Error Handling

by actionbook5c40d3ad7851No license1.5K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 6 weeks ago

CRITICAL: Use for error handling. Triggers: Result, Option, Error, ?, unwrap, expect, panic, anyhow, thiserror, when to panic vs return Result, custom error, error propagation, 错误处理, Result 用法, 什么时候用 panic

Instructions onlySoftware Development
AI-generated overview

Guides Rust error-handling choices between Result, Option, panic, thiserror and anyhow.

What it does
This instruction-only skill provides a decision framework for Rust error handling. It helps an agent decide whether a failure is expected or a bug, then choose between Result, Option, panic, thiserror and anyhow. It includes quick-reference tables, a decision flowchart, common errors, anti-patterns and pointers to related skills.
When to use it
Use it when writing or reviewing Rust code that involves Result, Option, ?, unwrap, expect, panic, anyhow or thiserror. It is meant for questions about when to panic versus return a Result, how to propagate errors with context, and how to design custom error types.
Requirements
No scripts or runtime dependencies; it is instructions only. It references Rust crates thiserror and anyhow as topics, but does not require them to be installed.

Error Handling

Layer 1: Language Mechanics

Core Question

Is this failure expected or a bug?

Before choosing error handling strategy:

  • Can this fail in normal operation?
  • Who should handle this failure?
  • What context does the caller need?

Error → Design Question

PatternDon't Just SayAsk Instead
unwrap panics"Use ?"Is None/Err actually possible here?
Type mismatch on ?"Use anyhow"Are error types designed correctly?
Lost error context"Add .context()"What does the caller need to know?
Too many error variants"Use Box<dyn Error>"Is error granularity right?

Thinking Prompt

Before handling an error:

  1. What kind of failure is this?

    • Expected → Result<T, E>
    • Absence normal → Option<T>
    • Bug/invariant → panic!
    • Unrecoverable → panic!
  2. Who handles this?

    • Caller → propagate with ?
    • Current function → match/if-let
    • User → friendly error message
    • Programmer → panic with message
  3. What context is needed?

    • Type of error → thiserror variants
    • Call chain → anyhow::Context
    • Debug info → anyhow or tracing

Trace Up ↑

When error strategy is unclear:

"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)
SituationTrace ToQuestion
Too many unwrapsm09-domainIs the data model right?
Error context designm13-domain-errorWhat recovery is needed?
Library vs app errorsm11-ecosystemWho are the consumers?

Trace Down ↓

From design to implementation:

"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")

Quick Reference

PatternWhenExample
Result<T, E>Recoverable errorfn read() -> Result<String, io::Error>
Option<T>Absence is normalfn find() -> Option<&Item>
?Propagate errorlet data = file.read()?;
unwrap()Dev/test onlyconfig.get("key").unwrap()
expect()Invariant holdsenv.get("HOME").expect("HOME set")
panic!Unrecoverablepanic!("critical failure")

Library vs Application

ContextError CrateWhy
LibrarythiserrorTyped errors for consumers
ApplicationanyhowErgonomic error handling
MixedBoththiserror at boundaries, anyhow internally

Decision Flowchart

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 ?

Common Errors

ErrorCauseFix
unwrap() panicUnhandled None/ErrUse ? or match
Type mismatchDifferent error typesUse anyhow or From
Lost context? without contextAdd .context()
cannot use ?Missing Result returnReturn Result<(), E>

Anti-Patterns

Anti-PatternWhy BadBetter
.unwrap() everywherePanics in production.expect("reason") or ?
Ignore errors silentlyBugs hiddenHandle or propagate
panic! for expected errorsBad UX, no recoveryResult
Box<dyn Error> everywhereLost type infothiserror

Related Skills

WhenSee
Domain error strategym13-domain-error
Crate boundariesm11-ecosystem
Type-safe errorsm05-type-driven
Mental modelsm14-mental-model

Source and attribution

Source:actionbook/rust-skillsinskills/m06-error-handlingat commit5c40d3a

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal