home / skills / dicklesworthstone / meta_skill / rust-error-handling

rust-error-handling skill

/skills/examples/rust-error-handling

This skill demonstrates Rust error handling patterns using thiserror and anyhow, promoting safe, ergonomic error propagation and test-friendly patterns.

npx playbooks add skill dicklesworthstone/meta_skill --skill rust-error-handling

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
1.7 KB
---
id: rust-error-handling
name: Rust Error Handling
description: >-
  Rust-specific error handling patterns, building on the base error handling
  skill. Demonstrates the 'extends' composition feature.
tags: [error-handling, rust, example]
extends: error-handling-base
---

# Rust Error Handling

Rust-specific error handling patterns that extend the base error handling skill.

## Rules

- Use `thiserror` for defining library error types
- Use `anyhow` for application-level error handling
- Implement `std::error::Error` trait for custom error types
- Use the `?` operator for ergonomic error propagation
- Prefer `Result<T, E>` over panicking for recoverable errors
- Use `unwrap()` only in tests or when failure is impossible

## Examples

```rust
// Define library errors with thiserror
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ConfigError {
    #[error("failed to read config file: {0}")]
    Io(#[from] std::io::Error),

    #[error("invalid config format: {0}")]
    Parse(#[from] toml::de::Error),

    #[error("missing required field: {field}")]
    MissingField { field: String },
}
```

```rust
// Application-level error handling with anyhow
use anyhow::{Context, Result};

fn load_config(path: &str) -> Result<Config> {
    let content = std::fs::read_to_string(path)
        .with_context(|| format!("failed to read config from {}", path))?;

    let config: Config = toml::from_str(&content)
        .context("failed to parse config TOML")?;

    Ok(config)
}
```

## Checklist

- [ ] Custom error types use `thiserror` derive
- [ ] Error context is added with `anyhow::Context`
- [ ] No `unwrap()` calls in production code paths
- [ ] `Result` is used instead of `panic!` for recoverable errors

Overview

This skill teaches Rust-specific error handling patterns built on a base error handling foundation. It shows when to define typed library errors, when to use application-level error wrappers, and practical rules to keep CLI and library code robust. The guidance is pragmatic and focused on common Rust tooling like thiserror and anyhow.

How this skill works

The skill inspects code and recommends patterns: derive error enums with thiserror for libraries, implement std::error::Error when needed, and prefer Result<T, E> for recoverable failures. For applications, it recommends anyhow for context-rich error propagation and demonstrates using the ? operator and Context helpers to attach actionable messages. It also enforces avoiding unwrap() in production code paths.

When to use it

  • When designing a library API that needs typed, inspectable errors.
  • When building an application or CLI that benefits from rich, contextual errors.
  • When migrating code that currently panics to a recoverable Result-based flow.
  • During code reviews to enforce consistent Rust error handling practices.
  • When adding diagnostics or user-facing messages to failing code paths.

Best practices

  • Define library error enums with thiserror derive to get Display and source wiring.
  • Use anyhow::Result and anyhow::Context in application entry points for readable traces.
  • Propagate errors with the ? operator and add context at boundary layers.
  • Avoid unwrap() except in tests or truly impossible branches; prefer Result returns.
  • Prefer Result<T, E> over panic! for recoverable errors and clear error composition.

Example use cases

  • Create a CLI that reads configuration files and returns user-facing errors with context.
  • Design a reusable library that exposes a typed ConfigError enum for callers to match on.
  • Refactor legacy code that uses panic! into Result-based flows with contextual messages.
  • Improve debugging by adding .with_context() around filesystem and parse operations.
  • Enforce no-unwrap rules in production code through linting and code review guidance.

FAQ

When should I use thiserror vs anyhow?

Use thiserror to define typed errors in libraries so callers can match on variants. Use anyhow in applications or top-level binaries to capture and display rich error context without exposing internal error types.

Is implementing std::error::Error always necessary?

For library error types you should implement or derive Error (thiserror does this). For ephemeral application errors wrapped by anyhow it is not required because anyhow erases concrete types.