// Package config provides configuration management functionality package config import ( "errors" "fmt" ) // Common config error types var ( // ErrFileNotFound indicates the config file does not exist ErrFileNotFound = errors.New("config file not found") // ErrFilePermission indicates permission issues with the config file ErrFilePermission = errors.New("insufficient permissions for config file") // ErrInvalidYAML indicates YAML parsing or syntax errors ErrInvalidYAML = errors.New("invalid YAML format") // ErrMissingRequired indicates a required field is missing ErrMissingRequired = errors.New("missing required field") // ErrInvalidValue indicates a field has an invalid value ErrInvalidValue = errors.New("invalid field value") // ErrInvalidSection indicates an invalid or missing config section ErrInvalidSection = errors.New("invalid config section") // ErrValidationFailed indicates config validation failure ErrValidationFailed = errors.New("config validation failed") // ErrInvalidAppName indicates an invalid application name ErrInvalidAppName = errors.New("invalid application name") // ErrInvalidEnvironment indicates an invalid environment ErrInvalidEnvironment = errors.New("invalid environment") ) // Error represents a configuration-specific error with detailed context type Error struct { // Op is the operation that failed (e.g., "read", "parse", "validate") Op string // Section is the config section involved (if applicable) Section string // Field is the specific field involved (if applicable) Field string // Value is the invalid value (if applicable) Value string // Err is the underlying error Err error // Details contains additional error context Details string } // Error returns a string representation of the error func (e *Error) Error() string { msg := fmt.Sprintf("config %s failed", e.Op) if e.Section != "" { msg = fmt.Sprintf("%s in section %q", msg, e.Section) } if e.Field != "" { msg = fmt.Sprintf("%s at field %q", msg, e.Field) } if e.Value != "" { msg = fmt.Sprintf("%s with value %q", msg, e.Value) } if e.Details != "" { msg = fmt.Sprintf("%s: %s", msg, e.Details) } if e.Err != nil { msg = fmt.Sprintf("%s: %v", msg, e.Err) } return msg } // Unwrap returns the underlying error func (e *Error) Unwrap() error { return e.Err } // Is reports whether target matches this error func (e *Error) Is(target error) bool { return errors.Is(e.Err, target) } // NewError creates a new config error func NewError(op string, err error, details string) *Error { return &Error{ Op: op, Err: err, Details: details, } } // NewFieldError creates a new config field error func NewFieldError(op string, section string, field string, value string, err error, details string) *Error { return &Error{ Op: op, Section: section, Field: field, Value: value, Err: err, Details: details, } } // IsValidationError returns true if the error indicates a validation problem func IsValidationError(err error) bool { var e *Error return errors.As(err, &e) && (errors.Is(e.Err, ErrValidationFailed) || errors.Is(e.Err, ErrMissingRequired) || errors.Is(e.Err, ErrInvalidValue)) } // IsFileError returns true if the error is related to file operations func IsFileError(err error) bool { var e *Error return errors.As(err, &e) && (errors.Is(e.Err, ErrFileNotFound) || errors.Is(e.Err, ErrFilePermission)) } // IsParseError returns true if the error is related to parsing func IsParseError(err error) bool { var e *Error return errors.As(err, &e) && errors.Is(e.Err, ErrInvalidYAML) }