mcpField
E
error-messages

error-messages

github.com/github开发5.5k59 次安装今天更新
代码仓库

关于 error-messages

供 gh-aw 开发者编写验证错误信息的风格指南,要求说明问题、预期格式和具体修复方式,并附有示例与测试建议。

主要功能

  1. 01按问题与修复组织错误信息
  2. 02倡导可执行的措辞
  3. 03区分验证错误与操作错误
  4. 04提供 YAML 和代码示例
  5. 05建议为改进后的信息编写测试

适用场景

  1. 01编写 gh-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]

确保每条错误消息都回答以下三个问题:

  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
  • 使用真实的 frontmatter 字段名称
  • 仅在 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)
选项/枚举验证
// 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

工具

编写错误消息时,请考虑:

  • 用户的角度(他们需要修复什么?)
  • 上下文(错误发生在工作流的哪个环节?)
  • 文档(是否应引用特定文档?)
  • 复杂程度(是否需要多行示例?)

评论

支持 Markdown