agentsclimarketplace

Rust error handling

Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/rust-error-handling

A curated pack of custom Claude Code skills for developers — installable as a Claude Code plugin marketplace.

Install
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill rust-error-handling

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

When to activate: Rust error handling, thiserror, anyhow, custom errors, Result, question mark operator, error propagation

SKILL.md

3.8 KB, as published. Nobody here has run it

Rust Error Handling

Custom Errors with thiserror

thiserror generates Display and Error impls from derive macros.

[dependencies]
thiserror = "2"
use thiserror::Error;

#[derive(Debug, Error)]
pub enum AppError {
    #[error("user {id} not found")]
    UserNotFound { id: u64 },

    #[error("database error: {0}")]
    Database(#[from] sqlx::Error),

    #[error("validation failed on field '{field}': {message}")]
    Validation { field: String, message: String },

    #[error("external service '{service}' returned {status}")]
    ExternalService { service: String, status: u16 },

    #[error(transparent)]
    Unexpected(#[from] anyhow::Error),
}

Application Errors with anyhow

anyhow is ideal for application code where you need rich context but don't care about the exact type.

[dependencies]
anyhow = "1"
use anyhow::{Context, Result, bail, ensure};

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 as TOML")?;

    ensure!(config.port > 1024, "port must be > 1024, got {}", config.port);

    if config.workers == 0 {
        bail!("workers must be at least 1");
    }

    Ok(config)
}

The ? Operator

? returns early on error, applying From conversion if needed.

fn process() -> Result<Output, AppError> {
    let data = read_file("input.txt")?;
    let parsed = parse_json(&data)?;
    let result = transform(parsed)?;
    Ok(result)
}

// ? works with Option via .ok_or / .ok_or_else
fn find_setting(name: &str) -> Result<String, AppError> {
    settings()
        .get(name)
        .cloned()
        .ok_or_else(|| AppError::Validation {
            field: name.to_string(),
            message: "setting not found".into(),
        })
}

Error Hierarchy (Library vs. Application)

// Library crates: use thiserror for typed, structured errors
#[derive(Debug, thiserror::Error)]
pub enum MyLibError {
    #[error("invalid input: {0}")]
    InvalidInput(String),
    #[error(transparent)]
    Io(#[from] std::io::Error),
}

// Application code: use anyhow for ergonomic context chains
fn run() -> anyhow::Result<()> {
    my_lib::process("data.txt")
        .context("processing step failed")?;
    Ok(())
}

Converting Between Error Types

// map_err for targeted conversion
fn parse_id(s: &str) -> Result<u64, AppError> {
    s.parse::<u64>().map_err(|e| AppError::Validation {
        field: "id".into(),
        message: e.to_string(),
    })
}

Error Handling in Main

fn main() -> anyhow::Result<()> {
    let config = load_config("config.toml")?;
    run(config)?;
    Ok(())
}

// With custom exit codes
fn main() {
    if let Err(e) = run() {
        eprintln!("Error: {e:#}"); // {:#} prints the full error chain
        std::process::exit(1);
    }
}

Common Anti-Patterns

  • Using Box<dyn Error> in library APIs — prevents callers from matching on specific errors
  • unwrap() / expect() in production code — always propagate or handle errors explicitly
  • Losing error context with bare ? — use .context() from anyhow to add what operation failed
  • Returning String as error type — hard for callers to programmatically handle
  • Swallowing errors in closures — log or propagate; never silently discard

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.