mcpField
E
error-messages

error-messages

github.com/github開発5.5k59 回インストール今日更新
リポジトリ

error-messages について

gh-aw の検証エラーを書く開発者向けのスタイルガイドです。問題点、期待される形式、具体的な修正例を示す構成と、例やテストの指針を説明します。

主な機能

  1. 01問題と修正を軸にエラーを構成
  2. 02実行可能な表現を推奨
  3. 03検証エラーと操作エラーを区別
  4. 04YAML とコードの例を掲載
  5. 05改善したメッセージのテストを推奨

活用シーン

  1. 01gh-aw の検証メッセージ作成
  2. 02曖昧な設定エラーの改善
  3. 03形式や型のエラーへの例の追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/github/gh-aw --skill error-messages

インストール後、Claude Code で/error-messagesを入力して読み込まれたか確認します。

同梱ファイルssl.json

詳細

エラーメッセージのスタイルガイド

gh-aw の検証エラーには、次の形式を使用してください。メッセージは明確で、対処方法がわかり、例を示すものにしてください。

エラーメッセージのテンプレート

[what's wrong]. [what's expected]. [example of correct usage]

各エラーメッセージで、次の3つの質問に答えてください。

  1. 何が問題ですか? - 検証エラーを明確に示します
  2. 何が期待されていますか? - 有効な形式や値を説明します
  3. どうすれば修正できますか? - 正しい使い方の具体例を示します

建設的な表現

否定的な表現だけを単独で使わないでください。期待される動作と具体的な修正方法を合わせて示します。

否定的な表現のみ建設的な表現
invalidexpected + 有効な形式/選択肢
cannotrequires + 前提条件
mustshould + 例
failed操作の状況 + 復旧手順

❌ invalid repo format: %s
✅ invalid repo format '%s' — expected 'owner/repo' format (for example: 'github/gh-aw')

❌ not in a git repository
✅ not in a git repository — run 'git init' or 'cd' to a git repository

NewValidationError と fmt.Errorf の使い分け

  • *_validation.go のロジックでは、NewValidationError(field, value, reason, suggestion) を使用します。
    • field には正確な設定パスを指定します
    • reason には失敗した理由を指定します
    • suggestion には、例を含む実行可能な修正方法を指定します
  • %w を使って下位レベルのエラーをコンテキストとともに伝播する、操作上のエラーやラップするエラーには fmt.Errorf を使用します。
  • 復旧方法を追加しない限り、fmt.Errorf("failed to X: %w", err) のような一般的なラッパーは避けてください。

提案文のチェックリスト

各 suggestion では、次のことを行ってください。

  1. 変更する内容を説明する
  2. 最小限の有効な YAML/コード例を含める
  3. 曖昧さが生じる可能性がある場合は ✓/✗ マーカーを使う

例:

Use one supported engine.
✓ Example:
engine: copilot

✗ Avoid:
engine: unknown

YAML の例に関するガイドライン

  • 最小限の有効な YAML の例を使う
  • 実際のフロントマターのフィールド名を使う
  • YAML で必要な場合にのみ引用符を付ける
  • 2スペースのインデントを推奨します

良い例

次の例はテンプレートに従い、具体的な対処方法を示しています。

時間差分の検証(time_delta.go より)
return nil, fmt.Errorf("invalid time delta format: +%s. Expected format like +25h, +3d, +1w, +1mo, +1d12h30m", deltaStr)

✅ 良い理由:

  • 無効な入力を明確に特定しています
  • 有効な形式の例を複数示しています
  • 組み合わせ形式(+1d12h30m)を示しています
例を含む型の検証
return "", fmt.Errorf("manual-approval value must be a string, got %T. Example: manual-approval: \"production\"", val)

✅ 良い理由:

  • 実際に受け取った型(%T)を示しています
  • 具体的な YAML の例を提示しています
  • 引用符を使った適切な YAML 構文になっています
選択肢を含む列挙型の検証
return fmt.Errorf("invalid engine: %s. Valid engines are: copilot, claude, codex, custom. Example: engine: copilot", engineID)

✅ 良い理由:

  • 有効な選択肢をすべて示しています
  • 最も簡単な例を提示しています
  • 一貫した書式を使っています
MCP の設定
return fmt.Errorf("tool '%s' mcp configuration must specify either 'command' or 'container'. Example:\ntools:\n  %s:\n    command: \"npx @my/tool\"", toolName, toolName)

✅ 良い理由:

  • 相互排他性を説明しています
  • 現実的なツール名を示しています
  • 複数行の YAML の例を整形して示しています

悪い例

次の例は明確さや具体的な対処方法に欠けています。

曖昧すぎる
return fmt.Errorf("invalid format")

❌ 問題点:

  • どの形式が無効なのかを指定していません
  • 期待される形式を説明していません
  • 例がありません
例がない
return fmt.Errorf("manual-approval value must be a string")

❌ 問題点:

  • 要件を示していますが、例がありません
  • 適切な YAML 構文がわかりません
  • 受け取った型をもっと明確に示せます
情報が不完全
return fmt.Errorf("invalid engine: %s", engineID)

❌ 問題点:

  • 有効な選択肢を列挙していません
  • エラーの修正方法を案内していません
  • ユーザーがドキュメントを探す必要があります

例を含める場合

次の場合は必ず例を含めてください。

  1. 形式/構文エラー - 正しい構文を示します

    fmt.Errorf("invalid date format. Expected: YYYY-MM-DD HH:MM:SS. Example: 2024-01-15 14:30:00")
    
  2. 列挙型/選択肢フィールド - 有効な選択肢をすべて列挙します

    fmt.Errorf("invalid permission level: %s. Valid levels: read, write, none. Example: permissions:\n  contents: read", level)
    
  3. 型の不一致 - 期待される型と例を示します

    fmt.Errorf("timeout-minutes must be an integer, got %T. Example: timeout-minutes: 10", value)
    
  4. 複雑な設定 - 完全で有効な例を示します

    fmt.Errorf("invalid MCP server config. Example:\nmcp-servers:\n  my-server:\n    command: \"node\"\n    args: [\"server.js\"]")
    

例を省略してもよい場合

次の場合は、例を省略できます。

  1. ラップされたエラーによるエラー - 別のエラーをコンテキストとともにラップする場合

    return fmt.Errorf("failed to parse configuration: %w", err)
    
  2. 明確なコンテキストがあり、エラーの内容が自明な場合

    return fmt.Errorf("duplicate unit '%s' in time delta: +%s", unit, deltaStr)
    
  3. エラーが具体的なドキュメントを参照している場合

    return fmt.Errorf("unsupported feature. See https://docs.example.com/features")
    

書式設定のガイドライン

動的な内容には型を表す動詞を使う
  • %s - 文字列
  • %d - 整数
  • %T - 値の型
  • %v - 一般的な値
  • %w - ラップされたエラー
複数行の例

複数行にわたる YAML 設定の例には、次の形式を使います。

fmt.Errorf("invalid config. Example:\ntools:\n  github:\n    mode: \"remote\"")
例での引用

例では適切な YAML 構文を使用してください:

// Good - shows quotes when needed
fmt.Errorf("Example: name: \"my-workflow\"")

// Good - shows no quotes for simple values
fmt.Errorf("Example: timeout-minutes: 10")
用語の一貫性

YAML と同じフィールド名を使用してください:

// Good - matches YAML field name
fmt.Errorf("timeout-minutes must be positive")

// Bad - uses different name
fmt.Errorf("timeout must be positive")

エラーメッセージのテスト

改善されたすべてのエラーメッセージには、対応するテストが必要です:

func TestErrorMessageQuality(t *testing.T) {
    err := validateSomething(invalidInput)
    require.Error(t, err)
    
    // Error should explain what's wrong
    assert.Contains(t, err.Error(), "invalid")
    
    // Error should include expected format or values
    assert.Contains(t, err.Error(), "Expected")
    
    // Error should include example
    assert.Contains(t, err.Error(), "Example:")
}

移行戦略

既存のエラーメッセージを改善する場合:

  1. エラーを特定する - 明確さに欠ける検証エラーを見つけます
  2. コンテキストを分析する - 何が検証されているのかを理解します
  3. テンプレートを適用する - 何が問題か + 期待される内容 + 例を追加します
  4. テストを追加する - エラーメッセージの内容を検証します
  5. コメントを更新する - 検証ロジックを文書化します

カテゴリ別の例

フォーマットの検証
// Time deltas
fmt.Errorf("invalid time delta format: +%s. Expected format like +25h, +3d, +1w, +1mo, +1d12h30m", input)

// Dates
fmt.Errorf("invalid date format: %s. Expected: YYYY-MM-DD or relative like -1w. Example: 2024-01-15 or -7d", input)

// URLs
fmt.Errorf("invalid URL format: %s. Expected: https:// URL. Example: https://api.example.com", input)
型の検証
// Boolean expected
fmt.Errorf("read-only must be a boolean, got %T. Example: read-only: true", value)

// String expected
fmt.Errorf("workflow name must be a string, got %T. Example: name: \"my-workflow\"", value)

// Object expected
fmt.Errorf("permissions must be an object, got %T. Example: permissions:\n  contents: read", value)
選択肢/Enum の検証
// Engine selection
fmt.Errorf("invalid engine: %s. Valid engines: copilot, claude, codex, custom. Example: engine: copilot", id)

// Permission levels
fmt.Errorf("invalid permission level: %s. Valid levels: read, write, none. Example: contents: read", level)

// Tool modes
fmt.Errorf("invalid mode: %s. Valid modes: local, remote. Example: mode: \"remote\"", mode)
設定の検証
// Missing required field
fmt.Errorf("tool '%s' missing required 'command' field. Example:\ntools:\n  %s:\n    command: \"node server.js\"", name, name)

// Mutually exclusive fields
fmt.Errorf("cannot specify both 'command' and 'container'. Choose one. Example: command: \"node server.js\"")

// Invalid combination
fmt.Errorf("http MCP servers cannot use 'container' field. Example:\ntools:\n  my-http:\n    type: http\n    url: \"https://api.example.com\"")

参考資料

  • 参考にすべき優れた例: pkg/workflow/time_delta.go
  • パターンのヒント: Go 標準ライブラリのエラーメッセージ
  • テストの例: pkg/workflow/*_test.go

ツール

エラーメッセージを書く際には、以下を考慮してください:

  • ユーザーの視点 (修正するために何が必要か?)
  • コンテキスト (ワークフローのどこでエラーが発生したか?)
  • ドキュメント (特定のドキュメントを参照すべきか?)
  • 複雑さ (複数行の例が必要か?)

コメント