plugins/rust-expert/skills/rust-error-handling/SKILL.md
Use when designing Rust error handling — picking thiserror for libraries vs anyhow for applications, building typed error enums, converting errors with
npx skillsauth add fusengine/agents rust-error-handlingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The consensus split: thiserror for libraries, anyhow for applications. A library
exposes a typed error its callers can match; an application wants one ergonomic error
type and rich context. Getting this boundary right is the whole discipline.
thiserror / anyhow API
before writing derives (verification chain: fuse-browser fast-path on
docs.rs/thiserror and docs.rs/anyhow → Context7 → Exa).cargo clippy.| Crate kind | Tool | Why |
|------------|------|-----|
| Library (others depend on it) | thiserror | Typed enum, #[derive(Error)], callers can match on variants |
| Application (binary, top level) | anyhow | anyhow::Result<T>, ? everywhere, .context() for breadcrumbs |
| Simple / dep-free | hand-written std::error::Error | No dependency when one or two variants suffice |
anyhow::Error in a library's public API. It erases the type, so
callers cannot match or handle specific failures. Return a typed enum error.
thiserror is designed to not appear in your public API — switching to/from a
hand-written impl is not a breaking change.anyhow; libraries use thiserror. Do not pull anyhow into
a reusable library's signatures..context("...") /
.with_context(|| ...) turns "No such file or directory" into a traceable chain.#[from] for zero-boilerplate conversion, so ? lifts a source error into your
enum. #[from] implies #[source] — never write both.Result for anything a caller could
reasonably recover from. Reserve panic!/unwrap/expect for broken invariants.| Topic | Reference | Load when |
|-------|-----------|-----------|
| thiserror (libraries) | thiserror-libraries.md | Building a typed error enum for a library API |
| anyhow (applications) | anyhow-applications.md | Handling errors in a binary / top-level app |
| Error design | error-design.md | Shaping enums, #[from] conversion, recoverable vs panic, the anyhow/thiserror boundary |
| Template | Load when | |----------|-----------| | library-error.md | Need a complete thiserror library error module | | application-error.md | Need a complete anyhow application entry point with context |
enum deriving thiserror::Error — no anyhow in the public APIanyhow::Result<T> and adds .context(...)#[from] used for source conversions; no redundant #[source] alongside it? used instead of unwrap() on fallible valuescargo clippy clean, sniper passedtesting
Copy self-audit and ban-lists — filler verbs/hype adjectives, slop placeholder names, fake-precise numbers, Title Case headlines, humor in error copy ('Oops!'), em-dash crutch, one copy register per page.
development
Logged-in web apps — dashboards, auth flows, settings, onboarding, data tables, command palettes, modals, toasts. Register `product`: density and glance-speed over marketing polish, no hero/CTA-tricks, every data surface covers empty/loading/error explicitly, tables and dataviz follow preattentive-processing rules.
development
Marketing sites, landing pages, campaign pages — register `brand` (design IS the product). Structure comes from the register's POV + a macrostructure pick, never from copying an inspiration site's section flow. Hero discipline, deviated section order, asymmetric grids, and a silhouette lookalike-test gate before ship.
development
Token-strategy core — OKLCH color rules, neutral tinting, accent-commitment levels, type scale, 8pt spacing grid, touch targets, and the canonical output format of design-system.md (the file the harness gates on). This is routing step 1 of design-method/SKILL.md — read it before design-web/design-webapp/design-ios/design-android, before picking or auditing a single color/type/spacing value.