Open
Description
Description
The application currently lacks a structured error categorization system. Implementing error categories would improve error handling, logging, monitoring, and user experience by providing clearer context about failure types.
Current Behavior
- Errors are wrapped with descriptive messages
- No systematic categorization of error types
- Difficult to handle different error types programmatically
- No clear separation between user errors vs system errors
Expected Behavior
- Implement error categories (Auth, Input, GitHub API, Internal, etc.)
- Provide structured error types with categories
- Enable programmatic error handling based on category
- Improve error messages and logging
Suggested Implementation
1. Define error categories:
// pkg/common/error_types.go
package common
type ErrorCategory int
const (
ErrorCategoryUnknown ErrorCategory = iota
ErrorCategoryAuth // Authentication/authorization errors
ErrorCategoryInput // Invalid input/validation errors
ErrorCategoryGitHub // GitHub API errors
ErrorCategoryNetwork // Network connectivity errors
ErrorCategoryRateLimit // Rate limiting errors
ErrorCategoryFilesystem // File system operation errors
ErrorCategoryInternal // Internal application errors
ErrorCategoryConfiguration // Configuration errors
)
func (c ErrorCategory) String() string {
categories := []string{
"Unknown",
"Authentication",
"Input Validation",
"GitHub API",
"Network",
"Rate Limit",
"Filesystem",
"Internal",
"Configuration",
}
if int(c) < len(categories) {
return categories[c]
}
return "Unknown"
}
2. Create categorized error type:
// CategorizedError wraps an error with a category
type CategorizedError struct {
Category ErrorCategory
Message string
Err error
}
func (e *CategorizedError) Error() string {
if e.Err != nil {
return fmt.Sprintf("[%s] %s: %v", e.Category, e.Message, e.Err)
}
return fmt.Sprintf("[%s] %s", e.Category, e.Message)
}
func (e *CategorizedError) Unwrap() error {
return e.Err
}
// Helper functions
func NewAuthError(message string, err error) error {
return &CategorizedError{
Category: ErrorCategoryAuth,
Message: message,
Err: err,
}
}
func NewInputError(message string, err error) error {
return &CategorizedError{
Category: ErrorCategoryInput,
Message: message,
Err: err,
}
}
// ... similar helpers for other categories
3. Update error handling throughout codebase:
// Example in githubutils.go
if resp != nil && resp.StatusCode == http.StatusUnauthorized {
return NewAuthError("GitHub authentication failed", err)
}
if resp != nil && resp.StatusCode == http.StatusForbidden && resp.Rate.Remaining == 0 {
return NewRateLimitError("GitHub API rate limit exceeded", err)
}
// Example in scanner.go
if version == "" {
return nil, NewInputError("invalid action reference format",
fmt.Errorf("missing version in: %s", ref))
}
4. Add error category checking utilities:
// GetErrorCategory extracts the category from an error
func GetErrorCategory(err error) ErrorCategory {
var catErr *CategorizedError
if errors.As(err, &catErr) {
return catErr.Category
}
return ErrorCategoryUnknown
}
// IsErrorCategory checks if an error belongs to a specific category
func IsErrorCategory(err error, category ErrorCategory) bool {
return GetErrorCategory(err) == category
}
5. Use in main application:
// In main.go
if err != nil {
category := common.GetErrorCategory(err)
switch category {
case common.ErrorCategoryAuth:
log.Fatalf("Authentication error: %v\nPlease check your GitHub token", err)
case common.ErrorCategoryInput:
log.Fatalf("Invalid input: %v", err)
case common.ErrorCategoryRateLimit:
log.Fatalf("Rate limit exceeded: %v\nPlease try again later", err)
default:
log.Fatalf("Error: %v", err)
}
}
Benefits
- Structured error handling
- Better error messages for users
- Easier debugging and monitoring
- Programmatic error handling
- Consistent error reporting
Migration Strategy
- Add error categorization infrastructure
- Gradually update error returns throughout codebase
- Update error handling in main and tests
- Document error categories in API documentation
Test Cases
- Verify error categorization works correctly
- Test error unwrapping maintains category
- Ensure backward compatibility
- Test category-based error handling
References
- Similar to Go 1.13+ error wrapping patterns
- Inspired by gRPC status codes
- Current error constants:
/pkg/common/error_util.go
Labels
- enhancement
- error-handling
- developer-experience