/m13-domain-error
Use when designing domain error handling. Keywords: domain error, error categorization, recovery strategy, retry, fallback, domain error hierarchy, user-facing vs internal errors, error code design, circuit breaker, graceful degradation, resilience, error context, backoff, retry
$ npx -y skills add zhanghandong/rust-skills --skill m13-domain-error --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/m13-domain-error
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when designing domain error handling. Keywords: domain error, error categorization, recovery strategy, retry, fallback, domain error hierarchy, user-facing vs internal errors, error code design, circuit breaker, graceful degradation, resilience, error context, backoff, retry
SKILL.md
m13-domain-error.SKILL.mdname: m13-domain-error
description: "Use when designing domain error handling. Keywords: domain error, error categorization, recovery strategy, retry, fallback, domain error hierarchy, user-facing vs internal errors, error code design, circuit breaker, graceful degradation, resilience, error context, backoff, retry with backoff, error recovery, transient vs permanent error, 领域错误, 错误分类, 恢复策略, 重试, 熔断器, 优雅降级"
user-invocable: false
Domain Error Strategy
> **Layer 2: Design Choices**
Core Question
**Who needs to handle this error, and how should they recover?**
Before designing error types:
- Is this user-facing or internal?
- Is recovery possible?
- What context is needed for debugging?
---
Error Categorization
| Error Type | Audience | Recovery | Example | |------------|----------|----------|---------| | User-facing | End users | Guide action | `InvalidEmail`, `NotFound` | | Internal | Developers | Debug info | `DatabaseError`, `ParseError` | | System | Ops/SRE | Monitor/alert | `ConnectionTimeout`, `RateLimited` | | Transient | Automation | Retry | `NetworkError`, `ServiceUnavailable` | | Permanent | Human | Investigate | `ConfigInvalid`, `DataCorrupted` |
---
Thinking Prompt
Before designing error types:
1. **Who sees this error?**
- End user → friendly message, actionable
- Developer → detailed, debuggable
- Ops → structured, alertable
2. **Can we recover?**
- Transient → retry with backoff
- Degradable → fallback value
- Permanent → fail fast, alert
3. **What context is needed?**
- Call chain → anyhow::Context
- Request ID → structured logging
- Input data → error payload
---
Trace Up ↑
To domain constraints (Layer 3):
"How should I handle payment failures?"
↑ Ask: What are the business rules for retries?
↑ Check: domain-fintech (transaction requirements)
↑ Check: SLA (availability requirements)| Question | Trace To | Ask | |----------|----------|-----| | Retry policy | domain-* | What's acceptable latency for retry? | | User experience | domain-* | What message should users see? | | Compliance | domain-* | What must be logged for audit? |
---
Trace Down ↓
To implementation (Layer 1):
"Need typed errors"
↓ m06-error-handling: thiserror for library
↓ m04-zero-cost: Error enum design
"Need error context"
↓ m06-error-handling: anyhow::Context
↓ Logging: tracing with fields
"Need retry logic"
↓ m07-concurrency: async retry patterns
↓ Crates: tokio-retry, backoff---
Quick Reference
| Recovery Pattern | When | Implementation | |------------------|------|----------------| | Retry | Transient failures | exponential backoff | | Fallback | Degraded mode | cached/default value | | Circuit Breaker | Cascading failures | failsafe-rs | | Timeout | Slow operations | `tokio::time::timeout` | | Bulkhead | Isolation | separate thread pools |
Error Hierarchy
#[derive(thiserror::Error, Debug)]
pub enum AppError {
// User-facing
#[error("Invalid input: {0}")]
Validation(String),
// Transient (retryable)
#[error("Service temporarily unavailable")]
ServiceUnavailable(#[source] reqwest::Error),
// Internal (log details, show generic)
#[error("Internal error")]
Internal(#[source] anyhow::Error),
}
impl AppError {
pub fn is_retryable(&self) -> bool {
matches!(self, Self::ServiceUnavailable(_))
}
}Retry Pattern
use tokio_retry::{Retry, strategy::ExponentialBackoff};
async fn with_retry<F, T, E>(f: F) -> Result<T, E>
where
F: Fn() -> impl Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
let strategy = ExponentialBackoff::from_millis(100)
.max_delay(Duration::from_secs(10))
.take(5);
Retry::spawn(strategy, || f()).await
}---
Common Mistakes
| Mistake | Why Wrong | Better | |---------|-----------|--------| | Same error for all | No actionability | Categorize by audience | | Retry everything | Wasted resources | Only transient errors | | Infinite retry | DoS self | Max attempts + backoff | | Expose internal errors | Security risk | User-friendly messages | | No context | Hard to debug | .context() everywhere |
---
Anti-Patterns
| Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | String errors | No structure | thiserror types | | panic! for recoverable | Bad UX | Result with context | | Ignore errors | Silent failures | Log or propagate | | Box<dyn Error> everywhere | Lost type info | thiserror | | Error in happy path | Performance | Early validation |
---
Related Skills
| When | See | |------|-----| | Error handling basics | m06-error-handling | | Retry implementation | m07-concurrency | | Domain modeling | m09-domain | | User-facing APIs | domain-* |
Read more
name: m13-domain-error description: "Use when designing domain error handling. Keywords: domain error, error categorization, recovery strategy, retry, fallback, domain error hierarchy, user-facing vs internal errors, error code design, circuit breaker, graceful degradation, resilience, error context, backoff, retry with backoff, error recovery, transient vs permanent error, 领域错误, 错误分类, 恢复策略, 重试, 熔断器, 优雅降级" user-invocable: false
Domain Error Strategy
> **Layer 2: Design Choices**
Core Question
**Who needs to handle this error, and how should they recover?**
Before designing error types:
- Is this user-facing or internal?
- Is recovery possible?
- What context is needed for debugging?
---
Error Categorization
| Error Type | Audience | Recovery | Example | |------------|----------|----------|---------| | User-facing | End users | Guide action | `InvalidEmail`, `NotFound` | | Internal | Developers | Debug info | `DatabaseError`, `ParseError` | | System | Ops/SRE | Monitor/alert | `ConnectionTimeout`, `RateLimited` | | Transient | Automation | Retry | `NetworkError`, `ServiceUnavailable` | | Permanent | Human | Investigate | `ConfigInvalid`, `DataCorrupted` |
---
Thinking Prompt
Before designing error types:
1. **Who sees this error?**
- End user → friendly message, actionable
- Developer → detailed, debuggable
- Ops → structured, alertable
2. **Can we recover?**
- Transient → retry with backoff
- Degradable → fallback value
- Permanent → fail fast, alert
3. **What context is needed?**
- Call chain → anyhow::Context
- Request ID → structured logging
- Input data → error payload
---
Trace Up ↑
To domain constraints (Layer 3):
"How should I handle payment failures?"
↑ Ask: What are the business rules for retries?
↑ Check: domain-fintech (transaction requirements)
↑ Check: SLA (availability requirements)| Question | Trace To | Ask | |----------|----------|-----| | Retry policy | domain-* | What's acceptable latency for retry? | | User experience | domain-* | What message should users see? | | Compliance | domain-* | What must be logged for audit? |
---
Trace Down ↓
To implementation (Layer 1):
"Need typed errors"
↓ m06-error-handling: thiserror for library
↓ m04-zero-cost: Error enum design
"Need error context"
↓ m06-error-handling: anyhow::Context
↓ Logging: tracing with fields
"Need retry logic"
↓ m07-concurrency: async retry patterns
↓ Crates: tokio-retry, backoff---
Quick Reference
| Recovery Pattern | When | Implementation | |------------------|------|----------------| | Retry | Transient failures | exponential backoff | | Fallback | Degraded mode | cached/default value | | Circuit Breaker | Cascading failures | failsafe-rs | | Timeout | Slow operations | `tokio::time::timeout` | | Bulkhead | Isolation | separate thread pools |
Error Hierarchy
#[derive(thiserror::Error, Debug)]
pub enum AppError {
// User-facing
#[error("Invalid input: {0}")]
Validation(String),
// Transient (retryable)
#[error("Service temporarily unavailable")]
ServiceUnavailable(#[source] reqwest::Error),
// Internal (log details, show generic)
#[error("Internal error")]
Internal(#[source] anyhow::Error),
}
impl AppError {
pub fn is_retryable(&self) -> bool {
matches!(self, Self::ServiceUnavailable(_))
}
}Retry Pattern
use tokio_retry::{Retry, strategy::ExponentialBackoff};
async fn with_retry<F, T, E>(f: F) -> Result<T, E>
where
F: Fn() -> impl Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
let strategy = ExponentialBackoff::from_millis(100)
.max_delay(Duration::from_secs(10))
.take(5);
Retry::spawn(strategy, || f()).await
}---
Common Mistakes
| Mistake | Why Wrong | Better | |---------|-----------|--------| | Same error for all | No actionability | Categorize by audience | | Retry everything | Wasted resources | Only transient errors | | Infinite retry | DoS self | Max attempts + backoff | | Expose internal errors | Security risk | User-friendly messages | | No context | Hard to debug | .context() everywhere |
---
Anti-Patterns
| Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | String errors | No structure | thiserror types | | panic! for recoverable | Bad UX | Result with context | | Ignore errors | Silent failures | Log or propagate | | Box<dyn Error> everywhere | Lost type info | thiserror | | Error in happy path | Performance | Early validation |
---
Related Skills
| When | See | |------|-----| | Error handling basics | m06-error-handling | | Retry implementation | m07-concurrency | | Domain modeling | m09-domain | | User-facing APIs | domain-* |
AI-powered Rust development assistant with meta-cognition framework
Other skills on rust-skills.
- /coding-guidelines
Use when asking about Rust code style or best practices. Keywords: naming, formatting, comment, clippy, rustfmt, lint, code style, best practice, P.NAM, G.FMT, code review, naming convention, variable naming, function naming, type naming, 命名规范, 代码风格, 格式化, 最佳实践, 代码审查, 怎么命名
Open skill - /core-actionbook
Internal support skill for actionbook MCP selectors used by Rust documentation research workflows. Use only when another rust-skills workflow explicitly requests actionbook-backed selectors.
Open skill - /core-agent-browser
Internal support skill for agent-browser CLI workflows used by rust-learner, docs-researcher, and crate-researcher. Use only when browser automation is explicitly required.
Open skill - /core-dynamic-skills
Internal command support for dynamic Rust crate skill management. Use only when explicitly invoked by /sync-crate-skills, /clean-crate-skills, or /update-crate-skill.
Open skill - /core-fix-skill-docs
Internal maintenance support for checking and fixing generated Rust skill documentation references. Use only when explicitly invoked by /fix-skill-docs.
Open skill - /domain-cli
Use when building CLI tools. Keywords: CLI, command line, terminal, clap, structopt, argument parsing, subcommand, interactive, TUI, ratatui, crossterm, indicatif, progress bar, colored output, shell completion, config file, environment variable, 命令行, 终端应用, 参数解析
Open skill

