errors

package
v1.1.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2025 License: MIT Imports: 3 Imported by: 0

README

Error Handling System

This package provides a comprehensive, categorized error handling system for the Hitch application. It replaces generic fmt.Errorf calls with structured, context-rich error types that improve debugging, error handling, and user experience.

Overview

The error handling system consists of:

  • Error Categories - Structured categorization of error types
  • HitchError - Base error type with context and categorization
  • Specific Error Types - Specialized errors for different domains
  • Error Utilities - Helper functions for error analysis and handling

Error Categories

type ErrorCategory int

const (
    CategoryUnknown ErrorCategory = iota
    CategoryValidation        // Input validation errors
    CategoryGitOperation      // Git-related operation errors
    CategoryUserInput         // User-provided input errors
    CategorySystem           // System-level errors (filesystem, permissions)
    CategoryMetadata         // Metadata-related errors
    CategoryRepository       // Repository state errors
)

Core Components

HitchError

The base error type that provides structured error information:

type HitchError struct {
    Category    ErrorCategory             // Error category for classification
    Message     string                   // Human-readable error message
    Details     string                   // Additional error details
    Underlying  error                   // Wrapped underlying error
    Context     map[string]interface{}   // Additional context information
}

Key Features:

  • Categorization - Every error has a specific category for programmatic handling
  • Context - Rich context information for debugging and logging
  • Error Wrapping - Proper error chain maintenance with Unwrap()
  • String Representation - Clean, formatted error messages
ValidationError

Used for input validation failures with field-specific information:

type ValidationError struct {
    Field   string  // Name of the field that failed validation
    Value   string  // The value that failed validation
    Reason  string  // Specific reason for validation failure
    Message string  // Formatted error message
}
GitOperationError

Specialized for Git-related operations with detailed command information:

type GitOperationError struct {
    Operation string  // Git operation that failed (merge, push, pull, etc.)
    Target    string  // Target of the operation (branch, remote, etc.)
    Reason    string  // Human-readable reason for failure
    Output    string  // Git command output for debugging
    ExitCode  int     // Exit code from git command
}
MergeConflictError

Specific to merge operations with file-level conflict information:

type MergeConflictError struct {
    Branch       string   // Source branch that caused conflicts
    ConflictFiles []string // List of files with conflicts
    Message      string   // Detailed conflict information
}

Usage Examples

Creating Validation Errors
import hitcherrors "github.com/DoomedRamen/hitch/internal/errors"

// Basic validation error
err := hitcherrors.NewBranchValidationError("feature/invalid", "contains dangerous characters")

// With custom details
err := hitcherrors.NewValidationError("invalid input", "must be alphanumeric")
Creating Git Operation Errors
// Git merge error
err := hitcherrors.NewGitMergeError("feature-branch", "conflicts detected", gitOutput)

// Git push error
err := hitcherrors.NewGitPushError("main", "origin", "authentication failed", pushOutput)

// Generic git command error
err := hitcherrors.NewGitCommandError("checkout", []string{"-b", "new-branch"}, "branch already exists", output)
Creating System Errors
// System error with underlying error
err := hitcherrors.NewSystemError("failed to access repository", os.ErrNotExist)

// Metadata error
err := hitcherrors.NewMetadataError("environment not found", "staging environment does not exist", nil)

// Repository error
err := hitcherrors.NewRepositoryError("repository is dirty", "uncommitted changes exist")
Adding Context to Errors
err := hitcherrors.NewValidationError("invalid branch name", "contains spaces").
    WithContext("branch_name", "feature invalid").
    WithContext("max_length", 255).
    WithContext("provided_length", len(branchName))
Error Analysis
// Check error category
if hitcherrors.IsCategory(err, hitcherrors.CategoryValidation) {
    // Handle validation error
}

// Extract error category
category := hitcherrors.GetCategory(err)
switch category {
case hitcherrors.CategoryGitOperation:
    // Handle git operation error
case hitcherrors.CategorySystem:
    // Handle system error
}

// Extract context information
if hErr, ok := err.(*hitcherrors.HitchError); ok {
    if branchName, exists := hErr.GetContext("branch_name"); exists {
        fmt.Printf("Failed branch: %v\n", branchName)
    }
}
Error Handling Patterns
1. Category-Based Error Handling
func handleCommandError(err error) error {
    if err == nil {
        return nil
    }

    switch hitcherrors.GetCategory(err) {
    case hitcherrors.CategoryValidation:
        return fmt.Errorf("validation failed: %w", err)
    case hitcherrors.CategoryGitOperation:
        return fmt.Errorf("git operation failed: %w", err)
    case hitcherrors.CategorySystem:
        return fmt.Errorf("system error: %w", err)
    default:
        return fmt.Errorf("unexpected error: %w", err)
    }
}
2. Contextual Error Enhancement
func validateAndCreateBranch(name string) error {
    if err := validateBranchName(name); err != nil {
        // Enhance validation error with additional context
        if hErr, ok := err.(*hitcherrors.HitchError); ok {
            return hErr.WithContext("operation", "branch_creation").
                         WithContext("timestamp", time.Now()).
                         WithContext("user", getCurrentUser())
        }
        return err
    }

    return createBranch(name)
}
3. Error Aggregation
func validateMultipleInputs(inputs map[string]string) error {
    var errors []hitcherrors.ValidationError

    for field, value := range inputs {
        if err := validateField(field, value); err != nil {
            if valErr, ok := err.(*hitcherrors.ValidationError); ok {
                errors = append(errors, *valErr)
            }
        }
    }

    if len(errors) == 0 {
        return nil
    }

    return hitcherrors.CombineValidationErrors(errors)
}

Migration Guide

Before (Old Pattern)
// Scattered error handling
if strings.Contains(branch, ";") {
    return fmt.Errorf("branch name contains dangerous character: ;")
}

if err := gitCommand(branch); err != nil {
    return fmt.Errorf("failed to create branch %s: %w", branch, err)
}

if len(branch) > 255 {
    return fmt.Errorf("branch name too long (max 255 characters)")
}
After (New Pattern)
import hitcherrors "github.com/DoomedRamen/hitch/internal/errors"

// Structured error handling
adapter := validation.BranchValidationAdapter()
if err := adapter.ValidateWithErrors(branch, "branch-name"); err != nil {
    return err // Returns properly categorized ValidationError
}

if err := gitCommand(branch); err != nil {
    return hitcherrors.NewGitBranchError(branch, "create", "git command failed", err.Error())
}

Benefits

  1. Consistency - All errors follow the same structure and patterns
  2. Debugging - Rich context information makes troubleshooting easier
  3. Programmatic Handling - Error categories enable automated error handling
  4. User Experience - Clear, actionable error messages
  5. Maintainability - Centralized error logic reduces duplication
  6. Testing - Structured errors are easier to test and mock

Best Practices

  1. Use Specific Error Types - Choose the most specific error type for your use case
  2. Provide Context - Add relevant context information for debugging
  3. Include Underlying Errors - Always wrap underlying errors when possible
  4. Clear Messages - Write human-readable error messages that explain the problem
  5. Categorize Correctly - Use the appropriate error category for programmatic handling

Integration

The error handling system integrates seamlessly with:

  • Validation Framework - internal/validation package uses these error types
  • Git Operations - All git package functions return structured errors
  • CLI Commands - Command handlers use category-based error handling
  • Logging System - Error context provides structured logging data

File Structure

internal/errors/
├── README.md              # This documentation
├── errors.go             # Base HitchError and utility functions
├── validation.go         # ValidationError and related functions
└── git_operations.go    # Git-specific error types and helpers

This error handling system provides a solid foundation for consistent, maintainable error handling throughout the Hitch application.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CombineValidationErrors

func CombineValidationErrors(errors []ValidationError) error

CombineValidationErrors combines multiple validation errors into a single error

func IsCategory

func IsCategory(err error, category ErrorCategory) bool

IsCategory checks if an error belongs to a specific category

Types

type ErrorCategory

type ErrorCategory int

Error categories for consistent error handling

const (
	// CategoryUnknown is for uncategorized errors
	CategoryUnknown ErrorCategory = iota
	// CategoryValidation is for input validation errors
	CategoryValidation
	// CategoryGitOperation is for git-related operation errors
	CategoryGitOperation
	// CategoryUserInput is for user-provided input errors
	CategoryUserInput
	// CategorySystem is for system-level errors (filesystem, permissions, etc.)
	CategorySystem
	// CategoryMetadata is for metadata-related errors
	CategoryMetadata
	// CategoryRepository is for repository state errors
	CategoryRepository
)

func GetCategory

func GetCategory(err error) ErrorCategory

GetCategory extracts the category from an error

func (ErrorCategory) String

func (c ErrorCategory) String() string

String implements the Stringer interface for the category

type GitOperationError

type GitOperationError struct {
	Operation string
	Target    string
	Reason    string
	Output    string
	ExitCode  int
}

GitOperationError represents git-specific operation errors

func NewGitBranchError

func NewGitBranchError(branch string, operation string, reason string, output string) *GitOperationError

NewGitBranchError creates a git branch operation error

func NewGitCheckoutError

func NewGitCheckoutError(ref string, reason string, output string) *GitOperationError

NewGitCheckoutError creates a git checkout error

func NewGitCommandError

func NewGitCommandError(command string, args []string, reason string, output string) *GitOperationError

NewGitCommandError creates a generic git command error

func NewGitMergeError

func NewGitMergeError(branch string, reason string, output string) *GitOperationError

NewGitMergeError creates a git merge error

func NewGitPullError

func NewGitPullError(branch string, remote string, reason string, output string) *GitOperationError

NewGitPullError creates a git pull error

func NewGitPushError

func NewGitPushError(branch string, remote string, reason string, output string) *GitOperationError

NewGitPushError creates a git push error

func (*GitOperationError) Error

func (e *GitOperationError) Error() string

func (*GitOperationError) Unwrap

func (e *GitOperationError) Unwrap() error

Unwrap implements error unwrapping

type HitchError

type HitchError struct {
	Category   ErrorCategory
	Message    string
	Details    string
	Underlying error
	Context    map[string]interface{}
}

HitchError is the base error type for all Hitch-specific errors

func NewGitOperationError

func NewGitOperationError(message string, details string, err error) *HitchError

NewGitOperationError creates a git operation error

func NewMetadataError

func NewMetadataError(message string, details string, err error) *HitchError

NewMetadataError creates a metadata error

func NewRepositoryError

func NewRepositoryError(message string, details string) *HitchError

NewRepositoryError creates a repository state error

func NewSystemError

func NewSystemError(message string, err error) *HitchError

NewSystemError creates a system error

func NewUserInputError

func NewUserInputError(message string, details ...string) *HitchError

NewUserInputError creates a user input error

func NewValidationError

func NewValidationError(message string, details ...string) *HitchError

NewValidationError creates a validation error

func (*HitchError) Error

func (e *HitchError) Error() string

Error implements the error interface

func (*HitchError) GetContext

func (e *HitchError) GetContext(key string) (interface{}, bool)

GetContext retrieves context information from an error

func (*HitchError) Unwrap

func (e *HitchError) Unwrap() error

Unwrap returns the underlying error for error unwrapping

func (*HitchError) WithContext

func (e *HitchError) WithContext(key string, value interface{}) *HitchError

WithContext adds context information to an error

type MergeConflictError

type MergeConflictError struct {
	Branch        string
	ConflictFiles []string
	Message       string
}

MergeConflictError represents merge conflicts

func NewMergeConflictError

func NewMergeConflictError(branch string, message string, conflictFiles []string) *MergeConflictError

NewMergeConflictError creates a merge conflict error

func (*MergeConflictError) Error

func (e *MergeConflictError) Error() string

type ValidationError

type ValidationError struct {
	Field   string
	Value   string
	Reason  string
	Message string
}

ValidationError holds specific validation error details

func NewBranchValidationError

func NewBranchValidationError(branchName string, reason string) *ValidationError

NewBranchValidationError creates a branch validation error

func NewCommitMessageValidationError

func NewCommitMessageValidationError(message string, reason string) *ValidationError

NewCommitMessageValidationError creates a commit message validation error

func NewEmailValidationError

func NewEmailValidationError(email string, reason string) *ValidationError

NewEmailValidationError creates an email validation error

func NewEnvironmentValidationError

func NewEnvironmentValidationError(envName string, reason string) *ValidationError

NewEnvironmentValidationError creates an environment validation error

func (*ValidationError) Error

func (e *ValidationError) Error() string

type ValidationResult

type ValidationResult struct {
	Errors  []ValidationError
	Valid   bool
	Details map[string]interface{}
}

ValidationResult contains multiple validation errors

func (*ValidationResult) Error

func (vr *ValidationResult) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL