---
sidebar_label: "エラー処理"
title: "エラー処理 - CyberGo html | 堅牢なエラー処理ガイド"
description: "CyberGo html エラー処理ガイド：5 種のエラー分類、errors.Is/As 判定、context キャンセル、バッチ部分失敗処理で堅牢なロジックを構築します。"
sidebar_position: 2
---

# エラー処理

## エラーの分類

HTML ライブラリのエラーは以下のカテゴリに分類されます：

| カテゴリ | センチネルエラー | 説明 |
|------|----------|------|
| 入力エラー | `ErrInputTooLarge`, `ErrInvalidHTML` | 入力コンテンツの問題 |
| 設定エラー | `ErrInvalidConfig`, `ErrMultipleConfigs` | 設定の問題 |
| ファイルエラー | `ErrFileNotFound`, `ErrInvalidFilePath` | ファイル操作の問題 |
| 処理エラー | `ErrProcessingTimeout`, `ErrMaxDepthExceeded` | 処理中の問題 |
| システムエラー | `ErrProcessorClosed`, `ErrInternalPanic` | 内部状態の問題 |

## errors.Is パターン

`errors.Is` でエラータイプを判定します：

```go
result, err := html.Extract(data)
if err != nil {
    switch {
    case errors.Is(err, html.ErrInputTooLarge):
        slog.Warn("入力が大きすぎます。ドキュメントサイズを小さくしてください")
    case errors.Is(err, html.ErrInvalidHTML):
        slog.Warn("無効な HTML です。入力を確認してください")
    case errors.Is(err, html.ErrProcessingTimeout):
        slog.Warn("処理がタイムアウトしました。ドキュメントが複雑すぎる可能性があります")
    case errors.Is(err, html.ErrFileNotFound):
        slog.Warn("ファイルが存在しません")
    case errors.Is(err, html.ErrMaxDepthExceeded):
        slog.Warn("DOM 深度が深すぎます。悪意のある構成の可能性があります")
    case errors.Is(err, html.ErrInternalPanic):
        slog.Error("内部パニックからリカバリしました。この問題を報告してください")
    default:
        slog.Error("不明なエラー", "err", err)
    }
}
```

## errors.As パターン

構造化されたエラー情報を抽出します：

```go
var inputErr *html.InputError
var configErr *html.ConfigError
var fileErr *html.FileError

if errors.As(err, &inputErr) {
    fmt.Printf("サイズ %d が制限 %d を超過\n", inputErr.Size, inputErr.MaxSize)
}

if errors.As(err, &configErr) {
    fmt.Printf("フィールド %s の値 %v が無効: %s\n", configErr.Field, configErr.Value, configErr.Message)
}

if errors.As(err, &fileErr) {
    fmt.Printf("ファイル操作: %s\n", fileErr.SafePath())
}
```

## コンテキストのキャンセル

`ExtractWithContext` バージョンを使用してキャンセルに対応します：

```go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

result, err := html.ExtractWithContext(ctx, data)
if err != nil {
    switch {
    case errors.Is(err, html.ErrProcessingTimeout):
        // ライブラリ内の ProcessingTimeout タイムアウト（この時点で ctx.Err() は nil の可能性あり）
    case ctx.Err() == context.DeadlineExceeded:
        // ユーザーコンテキストの期限切れ
    case ctx.Err() == context.Canceled:
        // 手動キャンセル
    default:
        // その他のエラー（ErrInvalidHTML、ErrInputTooLarge など）
        slog.Error("抽出失敗", "err", err)
    }
}
```

## バッチエラー

バッチ処理の結果には部分的な成功と部分的な失敗が含まれます：

```go
batch := p.ExtractBatch(pages)

for i, err := range batch.Errors {
    if err != nil {
        fmt.Printf("項目 %d が失敗: %v\n", i, err)
    }
}

fmt.Printf("成功：%d, 失敗：%d, キャンセル：%d\n",
    batch.Success, batch.Failed, batch.Cancelled)
```
