npx skills add ...
npx skills add github/gh-aw --skill error-messages
npx skills add github/gh-aw --skill error-messages
Write consistent, actionable validation error messages in gh-aw.
Use this format for gh-aw validation errors. Keep messages clear, actionable, and example-driven.
Make each error message answer three questions:
Avoid standalone negative wording. Pair it with expected behavior and a concrete fix.
| Avoid only-negative wording | Prefer constructive wording |
|---|---|
invalid | expected + valid format/options |
cannot | requires + precondition |
must | should + example |
failed | action context + recovery step |
❌ 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 vs fmt.ErrorfNewValidationError(field, value, reason, suggestion) in *_validation.go logic.
field for the exact config pathreason for what failedsuggestion for an actionable fix with an examplefmt.Errorf for operational/wrapping errors (%w) where you are propagating a lower-level failure with context.fmt.Errorf("failed to X: %w", err) unless you add recovery guidance.Every suggestion should:
Example:
These examples follow the template and provide actionable guidance:
✅ Why it's good:
✅ Why it's good:
✅ Why it's good:
✅ Why it's good:
These examples lack clarity or actionable guidance:
❌ Problems:
❌ Problems:
❌ Problems:
Always include examples for:
Format/Syntax Errors - Show the correct syntax
Enum/Choice Fields - List all valid options
Type Mismatches - Show expected type and example
Complex Configurations - Provide complete valid example
Examples can be omitted when:
Error is from wrapped error - When wrapping another error with context
Error is self-explanatory with clear context
Error points to specific documentation
%s - strings%d - integers%T - type of value%v - general value%w - wrapped errorsFor YAML configuration examples spanning multiple lines:
Use proper YAML syntax in examples:
Use the same field names as in YAML:
All improved error messages should have corresponding tests:
When improving existing error messages:
pkg/workflow/time_delta.gopkg/workflow/*_test.goWhen writing error messages, consider:
return fmt.Errorf("invalid engine: %s. Valid engines are: copilot, claude, codex, custom. Example: engine: copilot", engineID)return fmt.Errorf("tool '%s' mcp configuration must specify either 'command' or 'container'. Example:\ntools:\n %s:\n command: \"npx @my/tool\"", toolName, toolName)return fmt.Errorf("invalid format")return fmt.Errorf("manual-approval value must be a string")return fmt.Errorf("invalid engine: %s", engineID)