Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
zhanghandong avatar

M13 Domain Error

  • 752 installs
  • 1.3k repo stars
  • Updated May 24, 2026
  • zhanghandong/rust-skills

This is a copy of m13-domain-error by actionbook - installs and ranking accrue to the original listing.

m13-domain-error is a Rust agent skill that designs domain error hierarchies with recovery strategies for developers who need to separate user-facing messages from internal debug context and transient retry logic in back

About

m13-domain-error is Layer 2 design guidance in zhanghandong/rust-skills for Rust domain error handling. It asks who must handle each error and how recovery should work before defining error types, categorizing failures by audience and recoverability across user-facing, transient, and internal classes. A quick-reference table maps 5 recovery patterns—Retry with exponential backoff, Fallback defaults, Circuit Breaker via failsafe-rs, Timeout with tokio::time::timeout, and Bulkhead isolation—to concrete Rust implementations. The skill includes thiserror-based AppError hierarchies with is_retryable helpers and tokio_retry ExponentialBackoff examples. Developers reach for m13-domain-error when designing error codes, graceful degradation, or resilience patterns in production Rust APIs.

  • 5-tier error categorization (user-facing, internal, system, transient, permanent)
  • Decision framework answering who sees the error and whether recovery is possible
  • Explicit mapping of recovery strategies including retry with backoff, fallback, circuit breaker, and graceful degradatio
  • Separation of user-facing vs internal errors with tailored context and messaging
  • Domain error hierarchy and error code design guidance

M13 Domain Error by the numbers

  • 752 all-time installs (skills.sh)
  • +7 installs in the week ending Jul 28, 2026 (Skillselion tracking)
  • Security screen: MEDIUM risk (skills.sh audit)
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/zhanghandong/rust-skills --skill m13-domain-error

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs752
repo stars1.3k
Security audit3 / 3 scanners passed
Last updatedMay 24, 2026
Repositoryzhanghandong/rust-skills

How do you design recoverable domain errors in Rust?

Create clear, recoverable domain error strategies that distinguish user-facing messages from internal debug info and transient retry logic.

Who is it for?

Rust backend developers implementing thiserror-based domain errors who need structured recovery instead of generic error propagation.

Skip if: Developers writing trivial CLI scripts with single exit codes or teams not using Rust error handling libraries.

When should I use this skill?

User designs domain errors, error categorization, retry with backoff, circuit breakers, or user-facing versus internal Rust errors.

What you get

A categorized Rust error enum with recovery policies, user-facing messages, and retry or circuit-breaker implementations.

  • domain error enum
  • recovery policy implementation
  • user-facing error messages

By the numbers

  • Documents 5 recovery patterns in its quick-reference table
  • Classifies errors across user-facing, transient, and internal categories
  • Layer 2 skill in the zhanghandong/rust-skills error-design series

Files

SKILL.mdMarkdownGitHub ↗

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 TypeAudienceRecoveryExample
User-facingEnd usersGuide actionInvalidEmail, NotFound
InternalDevelopersDebug infoDatabaseError, ParseError
SystemOps/SREMonitor/alertConnectionTimeout, RateLimited
TransientAutomationRetryNetworkError, ServiceUnavailable
PermanentHumanInvestigateConfigInvalid, 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)
QuestionTrace ToAsk
Retry policydomain-*What's acceptable latency for retry?
User experiencedomain-*What message should users see?
Compliancedomain-*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 PatternWhenImplementation
RetryTransient failuresexponential backoff
FallbackDegraded modecached/default value
Circuit BreakerCascading failuresfailsafe-rs
TimeoutSlow operationstokio::time::timeout
BulkheadIsolationseparate 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

MistakeWhy WrongBetter
Same error for allNo actionabilityCategorize by audience
Retry everythingWasted resourcesOnly transient errors
Infinite retryDoS selfMax attempts + backoff
Expose internal errorsSecurity riskUser-friendly messages
No contextHard to debug.context() everywhere

---

Anti-Patterns

Anti-PatternWhy BadBetter
String errorsNo structurethiserror types
panic! for recoverableBad UXResult with context
Ignore errorsSilent failuresLog or propagate
Box<dyn Error> everywhereLost type infothiserror
Error in happy pathPerformanceEarly validation

---

Related Skills

WhenSee
Error handling basicsm06-error-handling
Retry implementationm07-concurrency
Domain modelingm09-domain
User-facing APIsdomain-*

Related skills

How it compares

Pick m13-domain-error over generic Rust error tutorials when you need recovery-policy design beyond basic Result propagation.

FAQ

What recovery patterns does m13-domain-error cover?

m13-domain-error documents 5 recovery patterns: Retry with exponential backoff, Fallback defaults, Circuit Breaker via failsafe-rs, Timeout with tokio::time::timeout, and Bulkhead thread-pool isolation.

How does m13-domain-error categorize Rust errors?

m13-domain-error classifies errors by audience and recoverability into user-facing validation errors, transient ServiceUnavailable failures, and internal errors that log details but return generic messages.

Is M13 Domain Error safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Backend & APIsbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.