smithery/See2et

rust-error-handling

Rustでのエラー設計を、境界ごとに thiserror / anyhow を使い分けて実?

Installation

$ npx skills add smithery/See2et --skill rust-error-handling

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,702 B
  • docs SUMMARY.md 285 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Rust Error Handling: anyhow / thiserror の境界設計

概要

目的

  • 例外的な失敗を「握りつぶさず」「原因を辿れる形」で伝搬し、境界で適切に変換する。
  • ドメイン層のAPIを型付きエラーで安定させ、上位で集約・ログ化・ユーザー向け変換ができるようにする。

適用範囲

  • ライブラリ/ドメイン層: thiserror による型付きエラー(Result<T, Error>)
  • アプリケーション境界(main/CLI/HTTPハンドラ等): anyhow::Result と .context() / .with_context()

やらないこと

  • ドメイン層の public API に anyhow::Error を露出しない。
  • 「とりあえず String エラー」で返さない(判断不能になる)。

前提となる役割分担

  • anyhow

- anyhow::Error と anyhow::Result<T> による「型消去された汎用エラー型」。 - アプリケーションコードでの「簡易なエラー統合・伝搬・コンテキスト付与」に用いる。

  • thiserror

- #[derive(Error)] で std::error::Error 実装を自動生成するためのクレート。 - ライブラリ/ドメイン層での「型付きエラー定義」に用いる。

  • ライブラリ/ドメイン層 → thiserror で意味のある Error 型を定義
  • アプリケーション境界(main など) → 複数の Error を anyhow でまとめて扱う

アプリケーション層(binary crate)でのルール — anyhow

  1. 戻り値は anyhow::Result<T> を使うのは「最上位だけ」

- main や CLI ハンドラ、HTTP サーバのエントリポイントなど、 「最終的にログを出して終了/レスポンスに変換する層」に限定して anyhow::Result<()> を使う。 - ドメインロジックにまで anyhow::Result を広げない。

```rust use anyhow::Result;

fn main() -> Result<()> { app::run()?; Ok(()) } ```

  1. .context() / .with_context() でエラーに文脈を必ず付ける

- 「どの操作中に失敗したのか」がわかるメッセージを付ける。

```rust use anyhow::{Context, Result};

fn loadconfig(path: &str) -> Result<String> { std::fs::readtostring(path) .withcontext(|| format!("failed to read config from {path}")) } ```

  1. 「ハンドルできない/ハンドルしない」境界でのみ anyhow に集約する

- HTTP レイヤや CLI レイヤで「ログを出す」「ユーザー向けメッセージに変換する」直前で、 下位の thiserror ベースのエラーを anyhow::Error に吸わせるのは OK。 - それより下の層では 独自 Error 型のまま 保つ。

  1. unwrap / expect の禁止(初期化コードなど例外的ケースを除く)

- ランタイムで発生しうる失敗はすべて Result / Option として扱い、? と anyhow / thiserror で処理する。

ライブラリ/ドメイン層でのルール — thiserror

  1. Public API では anyhow を返さず、自前の Error 型を定義する

- pub fn ... -> Result<T, Error> の Error は自前の enum / struct。 - anyhow::Error を public API に出すのは禁止。

```rust use thiserror::Error;

#[derive(Debug, Error)] pub enum RepositoryError { #[error("db error: {0}")] Db(#[from] sqlx::Error),

#[error("entity not found: {id}")] NotFound { id: String }, }

pub type Result<T> = std::result::Result<T, RepositoryError>; ```

  1. #[from] で外部エラーをラップし、source を保持する

- 依存クレートのエラーや IO エラーは、#[from] を使って自動変換する。 - これにより ? 演算子で自然に伝搬できる。

  1. エラー型は「使う側の判断に必要な粒度」で設計する

- 「ユーザー入力ミス」「外部サービスの障害」「内部バグ」など、 リトライ可否や HTTP ステータス変換などに必要な分類を enum variant として持たせる。

```rust #[derive(Debug, Error)] pub enum DomainError { #[error("invalid input: {0}")] InvalidInput(String),

#[error("external service failed: {0}")] External(String),

#[error("unexpected internal error")] Internal(#[from] anyhow::Error), // ← ドメイン内だけで包むのはアリ } ```

  1. Error 型はモジュール/境界ごとに分ける

- 1 つの巨大な Error enum に何でも詰め込まず、 「RepositoryError」「DomainError」「ApiError」のように責務ごとに分割する。

  1. thiserror エラーの Clone は条件付きで採用する

- 上位レイヤで「最後のエラー保持」「再利用」「再送」などが必要で、 かつ内包するエラー型が Clone を実装済みなら #[derive(Clone, Debug, Error)] を採用する。 - Clone が不要なエラー型にはむやみに付けない。

  1. Option<Error> の状態保持では参照アクセサを併設する

- Option<Error> をキャッシュする状態型では、 不要な clone を避けるため Option<&Error> を返す参照アクセサ(例: last_ref())を用意する。 - 文字列化やログ出力など「参照で足りる」処理は参照アクセサを使う。 - 既存 API 互換が必要な場合のみ、所有権を返すアクセサ(例: last())を併存させる。

チェックリスト

  • ドメイン層の public API は Result<T, DomainError>(または責務別Error)になっている
  • #[from] による source 保持ができている(原因追跡できる)
  • アプリ境界で .context() / .with_context() が付与されている
  • unwrap/expect が残っていない(例外: テスト、明示された初期化のみ)
  • HTTP/CLI変換が match で明示され、判断基準が読み取れる
  • Clone が必要な thiserror エラーだけに Clone derive を付与している
  • Option<Error> の状態保持型で、参照アクセサ(例: last_ref())を優先して不要 clone を避けている