errors

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2025 License: MIT Imports: 13 Imported by: 12

README ¶

Go Errors

A comprehensive error handling package that provides structured errors with rich context, location tracking, severity levels, error collection, validation support, retryable errors, and JSON serialization.

Features

  • Structured Error Types: Categorized errors with consistent structure across packages
  • Rich Context: Metadata, stack traces, request IDs, and timestamps
  • 🎯 Location Tracking: Automatic file/line location capture with runtime.Caller
  • 📊 Severity Levels: Hierarchical error classification (Debug, Info, Warning, Error, Critical, Fatal)
  • 📦 Error Collection: Thread-safe aggregation and batch error handling with analysis
  • Validation Support: Built-in handling for field-level validation errors with ozzo-validation integration
  • Retryable Errors: Support for retryable errors with exponential backoff
  • JSON Serialization: Full JSON marshaling/unmarshaling support
  • Error Wrapping: Compatible with Go's errors.Is and errors.As
  • Fluent Interface: Chainable methods for building complex errors
  • Code Support: Both numeric and text codes for easy error identification
  • HTTP Integration: Built-in HTTP status code mapping and error response structures
  • Logging Support: Enhanced slog integration with severity-based logging and collector attributes
  • Production Ready: Configurable features with build tags for performance optimization

Installation

go get github.com/goliatone/go-errors

Quick Start

package main

import (
    "fmt"
    "github.com/goliatone/go-errors"
)

func main() {
    // Create a simple error - note the parameter order change
    err := errors.New("user not found", errors.CategoryNotFound)

    // Add context using fluent interface
    enrichedErr := err.
        WithMetadata(map[string]any{"user_id": 123}).
        WithRequestID("req-456").
        WithStackTrace().
        WithCode(404).
        WithTextCode("USER_NOT_FOUND")

    fmt.Println(enrichedErr.Error())

    // Create a validation error
    validationErr := errors.NewValidation("invalid input",
        errors.FieldError{Field: "email", Message: "required"},
        errors.FieldError{Field: "age", Message: "must be positive"},
    )

    // Wrap an existing error
    wrappedErr := errors.Wrap(err, errors.CategoryInternal, "database query failed")
}

Error Categories

The package provides a set of predefined error categories:

  • CategoryValidation - Input validation failures
  • CategoryAuth - Authentication errors
  • CategoryAuthz - Authorization errors
  • CategoryOperation - Operation failures
  • CategoryNotFound - Resource not found
  • CategoryConflict - Resource conflicts
  • CategoryRateLimit - Rate limiting errors
  • CategoryBadInput - Malformed input
  • CategoryInternal - Internal system errors
  • CategoryExternal - External service errors
  • CategoryMiddleware - Middleware errors
  • CategoryRouting - Routing errors
  • CategoryHandler - Handler errors
  • CategoryMethodNotAllowed - HTTP method not allowed
  • CategoryCommand - Command execution errors

Enhanced Features

🎯 Location Tracking

Automatically capture the file, line, and function where errors are created:

// Automatic location capture (enabled by default)
err := errors.New("database connection failed", errors.CategoryExternal)
fmt.Printf("Error occurred at: %s\n", err.GetLocation().String())
// Output: Error occurred at: main.go:25

// Explicit location capture
err = errors.New("critical error").WithLocation(errors.Here())

// Check if error has location
if err.HasLocation() {
    loc := err.GetLocation()
    fmt.Printf("File: %s, Line: %d, Function: %s\n", 
        loc.File, loc.Line, loc.Function)
}

// Configure location capture globally
errors.SetLocationCapture(false) // Disable for production
errors.SetLocationCapture(true)  // Re-enable

// Environment variable control
// GO_ERRORS_DISABLE_LOCATION=true disables location capture
📊 Severity Levels

Classify errors by severity with built-in level hierarchy:

// Severity levels (from lowest to highest)
// SeverityDebug, SeverityInfo, SeverityWarning, 
// SeverityError, SeverityCritical, SeverityFatal

// Create errors with specific severity
debugErr := errors.NewDebug("Cache miss", errors.CategoryInternal)
infoErr := errors.NewInfo("User logged in", errors.CategoryAuth)
warningErr := errors.NewWarning("Rate limit approaching", errors.CategoryRateLimit)
errorErr := errors.New("Validation failed", errors.CategoryValidation) // Default: Error
criticalErr := errors.NewCritical("Database down", errors.CategoryExternal)

// Set severity on existing errors
err := errors.New("system issue").WithSeverity(errors.SeverityCritical)

// Check severity levels
if err.IsAboveSeverity(errors.SeverityWarning) {
    // Handle serious errors
}

if err.HasSeverity(errors.SeverityCritical) {
    // Handle critical errors specifically
}

// Get severity level
severity := err.GetSeverity()
fmt.Printf("Error severity: %s\n", severity) // Output: CRITICAL

// Severity-based logging (automatically maps to slog levels)
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
errors.LogBySeverity(logger, err) // Logs with appropriate level
📦 Error Collection

Collect and aggregate multiple errors with thread-safe operations:

// Create error collector with options
collector := errors.NewCollector(
    errors.WithMaxErrors(50),
    errors.WithStrictMode(false), // false = FIFO when full
    errors.WithContext(context.Background()),
)

// Add various types of errors
collector.Add(errors.NewValidation("Email invalid", 
    errors.FieldError{Field: "email", Message: "required"}))
collector.AddValidation("age", "must be positive")
collector.AddRetryable(nil, errors.CategoryExternal, "Service timeout")

// Basic collector operations
fmt.Printf("Total errors: %d\n", collector.Count())
fmt.Printf("Has errors: %t\n", collector.HasErrors())
fmt.Printf("Has retryable: %t\n", collector.HasRetryableErrors())

// Error analysis and filtering
categoryStats := collector.CategoryStats()
// Returns: map[Category]int{CategoryValidation: 2, CategoryExternal: 1}

severityStats := collector.SeverityDistribution()
// Returns: map[Severity]int{SeverityError: 2, SeverityWarning: 1}

mostCommon := collector.MostCommonCategory()
criticalErrors := collector.FilterBySeverity(errors.SeverityCritical)
validationErrors := collector.FilterByCategory(errors.CategoryValidation)

// Aggregate errors into a single error
merged := collector.Merge()
// Creates single error with metadata containing statistics

// Convert to HTTP response
httpResponse := collector.ToErrorResponse(false)
jsonData, _ := json.Marshal(httpResponse)

// Structured logging for all collected errors
collector.LogErrors(logger) // Logs each error with collector context

// Reset collector for reuse
collector.Reset()
Advanced Usage Patterns
Batch Processing with Error Collection
func processBatch(items []Item) error {
    collector := errors.NewCollector(errors.WithMaxErrors(100))
    
    for _, item := range items {
        if err := processItem(item); err != nil {
            collector.Add(err)
        }
    }
    
    if !collector.HasErrors() {
        return nil // All items processed successfully
    }
    
    // Analyze errors to determine strategy
    retryableCount := len(collector.GetRetryableErrors())
    criticalCount := len(collector.FilterBySeverity(errors.SeverityCritical))
    
    if criticalCount > 0 {
        // Abort batch due to critical errors
        return collector.Merge()
    } else if retryableCount > collector.Count()/2 {
        // Retry entire batch if mostly retryable errors
        return errors.NewRetryable("Batch has retryable errors", 
            errors.CategoryOperation).BaseError
    }
    
    // Return aggregated error for individual item handling
    return collector.Merge()
}
Web API Error Handling
func registerUser(req UserRequest) (*UserResponse, error) {
    collector := errors.NewCollector()
    
    // Validate input
    if req.Email == "" {
        collector.AddValidation("email", "email is required")
    }
    if req.Age < 18 {
        collector.AddValidation("age", "must be 18 or older")
    }
    
    // Check business rules
    if isReservedUsername(req.Username) {
        collector.Add(errors.New("Username reserved", errors.CategoryConflict).
            WithCode(409).WithTextCode("USERNAME_RESERVED"))
    }
    
    // External service checks
    if err := validateEmailWithService(req.Email); err != nil {
        collector.AddRetryable(err, errors.CategoryExternal, 
            "Email validation service failed")
    }
    
    if collector.HasErrors() {
        // Return HTTP-ready error response
        return nil, collector.Merge()
    }
    
    // Proceed with user creation...
    return &UserResponse{}, nil
}

Core Types

Error

The main error type that carries all error information:

type Error struct {
    Category         Category           `json:"category"`
    Code             int                `json:"code,omitempty"`
    TextCode         string             `json:"text_code,omitempty"`
    Message          string             `json:"message"`
    Source           error              `json:"-"`
    ValidationErrors ValidationErrors   `json:"validation_errors,omitempty"`
    Metadata         map[string]any     `json:"metadata,omitempty"`
    RequestID        string             `json:"request_id,omitempty"`
    Timestamp        time.Time          `json:"timestamp"`
    StackTrace       StackTrace         `json:"stack_trace,omitempty"`
    Location         *ErrorLocation     `json:"location,omitempty"`      // NEW: Location tracking
    Severity         Severity           `json:"severity"`                // NEW: Severity level
}
ValidationErrors

For handling multiple field-level validation errors:

type ValidationErrors []FieldError

type FieldError struct {
    Field   string `json:"field"`
    Message string `json:"message"`
    Value   any    `json:"value,omitempty"`
}
ErrorLocation

For capturing error location information:

type ErrorLocation struct {
    File     string `json:"file"`     // Full file path
    Line     int    `json:"line"`     // Line number
    Function string `json:"function"` // Function name
}
Severity

For error classification by severity level:

type Severity int

const (
    SeverityDebug Severity = iota    // Debug information
    SeverityInfo                     // Informational messages  
    SeverityWarning                  // Warning conditions
    SeverityError                    // Error conditions (default)
    SeverityCritical                 // Critical conditions
    SeverityFatal                    // Fatal conditions
)
ErrorCollector

For aggregating multiple errors:

type ErrorCollector struct {
    // Internal fields (thread-safe)
}

// Functional options for configuration
type CollectorOption func(*ErrorCollector)

// Option functions:
// WithMaxErrors(max int) - Set maximum errors (default: 100)
// WithStrictMode(strict bool) - Enable strict mode (default: false)  
// WithContext(ctx context.Context) - Set context

Constructor Functions

Basic Constructors
// New creates an error with message and optional category (defaults to CategoryInternal)
err := errors.New("resource not found", errors.CategoryNotFound)

// Wrap an existing error with additional context
wrappedErr := errors.Wrap(sourceErr, errors.CategoryInternal, "operation failed")
Validation Constructors
err := errors.NewValidation("validation failed",
    errors.FieldError{Field: "email", Message: "invalid format"},
    errors.FieldError{Field: "age", Message: "must be positive"},
)

// From a map
fieldMap := map[string]string{
    "name": "required",
    "email": "invalid format",
}
err := errors.NewValidationFromMap("validation failed", fieldMap)

// From grouped errors (useful for complex validations)
groups := map[string][]string{
    "user": {"name required", "email invalid"},
    "address": {"city required"},
}
err := errors.NewValidationFromGroups("validation failed", groups)
Severity-Based Constructors
// Create errors with specific severity levels
debugErr := errors.NewDebug("Debug info", errors.CategoryInternal)
infoErr := errors.NewInfo("User action", errors.CategoryAuth)  
warningErr := errors.NewWarning("Resource low", errors.CategoryOperation)
criticalErr := errors.NewCritical("System failing", errors.CategoryInternal)

// Default constructor creates SeverityError
errorErr := errors.New("Something failed", errors.CategoryValidation)
Collector Constructors
// Create error collector with default settings
collector := errors.NewCollector()

// Create collector with custom configuration
collector := errors.NewCollector(
    errors.WithMaxErrors(200),
    errors.WithStrictMode(true),
    errors.WithContext(ctx),
)
Location-Aware Constructors
// Automatic location capture (default behavior)
err := errors.New("error message", errors.CategoryInternal)

// Explicit location setting  
err := errors.NewWithLocation("error message", 
    errors.CategoryInternal, errors.Here())

// Disable location for this error only
errors.SetLocationCapture(false)
err := errors.New("no location", errors.CategoryInternal)
errors.SetLocationCapture(true)

Fluent Interface

Chain methods to build rich error context:

err := errors.New("authentication failed", errors.CategoryAuth).
    WithCode(401).
    WithTextCode("AUTH_FAILED").
    WithSeverity(errors.SeverityCritical).           // NEW: Set severity
    WithLocation(errors.Here()).                     // NEW: Set location
    WithMetadata(map[string]any{
        "user_id": 123,
        "attempt": 3,
    }).
    WithRequestID("req-789").
    WithStackTrace()

// Additional fluent methods for enhanced features:
err = err.WithSeverity(errors.SeverityWarning)      // Change severity
if err.HasLocation() {                               // Check location
    fmt.Printf("Location: %s\n", err.GetLocation().String())
}
if err.IsAboveSeverity(errors.SeverityInfo) {       // Check severity threshold
    // Handle serious errors
}

Error Checking

The package provides utility functions to check error types and categories:

// Check specific error categories
if errors.IsValidation(err) {
    // Handle validation error
}

if errors.IsAuth(err) {
    // Handle authentication error
}

if errors.IsNotFound(err) {
    // Handle not found error
}

if errors.IsInternal(err) {
    // Handle internal error
}

if errors.IsCommand(err) {
    // Handle command error
}

// Check any category
if errors.IsCategory(err, errors.CategoryRateLimit) {
    // Handle rate limit error
}

// Check if category exists anywhere in error chain
if errors.HasCategory(err, errors.CategoryExternal) {
    // Handle external service error (even if wrapped)
}

// Extract validation errors
if validationErrs, ok := errors.GetValidationErrors(err); ok {
    for _, fieldErr := range validationErrs {
        fmt.Printf("%s: %s\n", fieldErr.Field, fieldErr.Message)
    }
}

// Use standard library error functions
if errors.Is(err, originalErr) {
    // Handle specific error
}

var myErr *errors.Error
if errors.As(err, &myErr) {
    // Access structured error fields
    fmt.Println(myErr.Category)
}

// Get root cause of error chain
rootErr := errors.RootCause(err)

// Get root category from error chain
rootCategory := errors.RootCategory(err)

// NEW: Enhanced error checking with severity and location
if err.HasSeverity(errors.SeverityCritical) {
    // Handle critical errors
}

if err.IsAboveSeverity(errors.SeverityWarning) {
    // Handle serious errors (Warning, Error, Critical, Fatal)
}

severity := err.GetSeverity()
fmt.Printf("Error severity: %s\n", severity)

if err.HasLocation() {
    loc := err.GetLocation()
    fmt.Printf("Error at %s:%d in %s\n", loc.File, loc.Line, loc.Function)
}

JSON Serialization

Errors implement JSON marshaling for API responses:

err := errors.New("validation failed", errors.CategoryValidation).
    WithCode(400).
    WithSeverity(errors.SeverityWarning).
    WithMetadata(map[string]any{"field": "email"})

data, _ := json.Marshal(err)
fmt.Println(string(data))
// Output: {"category":"validation","code":400,"message":"validation failed","metadata":{"field":"email"},"timestamp":"2023-01-01T12:00:00Z","location":{"file":"main.go","line":42,"function":"main.main"},"severity":"WARNING"}

// Create an error response for APIs
errResp := err.ToErrorResponse(false, nil) // excludes stack trace
responseData, _ := json.Marshal(errResp)

// Error collector JSON serialization
collector := errors.NewCollector()
collector.Add(err)
collector.AddValidation("name", "required")

collectorResponse := collector.ToErrorResponse(false)
// Returns aggregated error with metadata about collected errors

Stack Traces

Capture stack traces for debugging:

err := errors.New("system error", errors.CategoryInternal).WithStackTrace()

// Print error with stack trace
fmt.Println(err.ErrorWithStack())

Retryable Errors

The package provides support for retryable errors with exponential backoff:

// Create a retryable error
retryErr := errors.NewRetryable("service unavailable", errors.CategoryExternal).
    WithRetryDelay(2 * time.Second).
    WithCode(503)

// Create a retryable operation error with default 500ms delay
opErr := errors.NewRetryableOperation("operation failed")

// Create a retryable external service error
extErr := errors.NewRetryableExternal("external API error")

// Create a non-retryable error
nonRetryErr := errors.NewNonRetryable("invalid credentials", errors.CategoryAuth)

// Check if error is retryable
if errors.IsRetryableError(err) {
    // Calculate delay for attempt 3
    if retryableErr, ok := err.(*errors.RetryableError); ok {
        delay := retryableErr.RetryDelay(3) // exponential backoff
    }
}

HTTP Integration

The package includes HTTP error mapping and response utilities:

// Map HTTP errors to structured errors
httpErr := errors.MapHTTPErrors(err)

// Convert category to HTTP status code
status := errors.HTTPStatusToCategory(404) // returns CategoryNotFound

// Generate text code from HTTP status
textCode := errors.HTTPStatusToTextCode(404) // returns "NOT_FOUND"

// Use predefined HTTP status constants
err := errors.New("not found", errors.CategoryNotFound).
    WithCode(errors.CodeNotFound) // 404

// Map errors with custom mappers
mappedErr := errors.MapToError(err, errors.DefaultErrorMappers())

Enhanced Logging Integration

Integrate with structured logging using slog with enhanced features:

import "log/slog"

// Convert error to slog attributes (now includes severity and location)
attrs := errors.ToSlogAttributes(err)
slog.Error("operation failed", attrs...)

// Attributes include: error_code, text_code, category, severity, request_id,
// validation_errors, metadata, and location information

// NEW: Severity-based logging (automatically uses appropriate slog level)
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
errors.LogBySeverity(logger, err)
// Maps SeverityDebug->Debug, SeverityInfo->Info, SeverityWarning->Warn,
// SeverityError->Error, SeverityCritical->Error+Stack, SeverityFatal->Error+Stack

// NEW: Error collector logging
collector := errors.NewCollector()
collector.Add(errors.NewWarning("Warning 1", errors.CategoryOperation))
collector.Add(errors.NewCritical("Critical issue", errors.CategoryExternal))

// Log all collected errors with collector context
collector.LogErrors(logger)

// Get collector-specific attributes
collectorAttrs := collector.ToSlogAttributes()
logger.Info("Error summary", collectorAttrs...)
// Includes: error_count, category_stats, severity_stats, most_common_category,
// validation_error_count, retryable_error_count

Validation Methods

The Error type provides additional validation helper methods:

// Get all validation errors as a map (including nested)
validationMap := err.ValidationMap()
// Returns: map[string]string{"email": "required", "age": "must be positive"}

// Get all validation errors including wrapped errors
allErrors := err.AllValidationErrors()
// Returns: []FieldError with all validation errors in the chain

// Clone an error for modification
clonedErr := err.Clone()
clonedErr.WithMetadata(map[string]any{"new_field": "value"})

Global Configuration

Enhanced Configuration Options
// Enable verbose error output (includes location in Error() string)
errors.Verbose = true

// Set development mode for detailed debugging
errors.IsDevelopment = true

// NEW: Location tracking configuration
errors.SetLocationCapture(true)   // Enable location capture (default)
errors.SetLocationCapture(false)  // Disable for production performance

// Check current location capture state
enabled := errors.IsLocationCaptureEnabled()

// Environment variable configuration
// Set GO_ERRORS_DISABLE_LOCATION=true to disable location capture
Performance Considerations

The enhanced features are designed with performance in mind:

  • Location Capture: ~400ns overhead per error (can be disabled in production)
  • Severity Levels: Zero overhead - stored as integers
  • Error Collection: ~90ns per Add operation with thread-safe mutex
  • Memory Usage: ~1KB per 10 collected errors
// Production configuration example
func init() {
    if os.Getenv("ENV") == "production" {
        errors.SetLocationCapture(false)  // Disable location for performance
        errors.Verbose = false            // Disable verbose output
    }
}
Build Tag Support

For advanced production optimization, you can use build tags:

# Build with production optimizations (disables expensive features)
go build -tags prod

# Development build (all features enabled)
go build

License

MIT License, see LICENSE file for details.

Documentation ¶

Index ¶

Constants ¶

View Source
const (
	CodeNotFound        = http.StatusNotFound
	CodeConflict        = http.StatusConflict
	CodeBadRequest      = http.StatusBadRequest
	CodeForbidden       = http.StatusForbidden
	CodeInternal        = http.StatusInternalServerError
	CodeUnauthorized    = http.StatusUnauthorized
	CodeRequestTimeout  = http.StatusRequestTimeout
	CodeTooManyRequests = http.StatusTooManyRequests
)

Variables ¶

View Source
var (
	Verbose       = false
	IsDevelopment = false
)

Global behavior

View Source
var (
	As     = goerrors.As
	Is     = goerrors.Is
	Unwrap = goerrors.Unwrap
	Join   = goerrors.Join
)
View Source
var (
	// EnableLocationCapture controls whether location information is captured for new errors
	// This can be disabled in production for performance optimization
	EnableLocationCapture = true
)

Global configuration for location capture

Functions ¶

func HTTPStatusToTextCode ¶ added in v0.3.0

func HTTPStatusToTextCode(code int) string

HTTPStatusToTextCode generates text codes from HTTP status codes

func HasCategory ¶ added in v0.8.0

func HasCategory(err error, category Category) bool

TODO: Should this be how IsCategory actually functions?!

func IsAuth ¶

func IsAuth(err error) bool

func IsCategory ¶

func IsCategory(err error, category Category) bool

func IsCommand ¶ added in v0.5.0

func IsCommand(err error) bool

func IsInternal ¶

func IsInternal(err error) bool

func IsLocationCaptureEnabled ¶ added in v0.9.0

func IsLocationCaptureEnabled() bool

IsLocationCaptureEnabled returns whether location capture is currently enabled

func IsNotFound ¶

func IsNotFound(err error) bool

func IsRetryableError ¶ added in v0.5.0

func IsRetryableError(err error) bool

IsRetryableError checks if an error implements the IsRetryable interface and returns true

func IsValidation ¶

func IsValidation(err error) bool

func IsWrapped ¶ added in v0.5.1

func IsWrapped(err error) bool

IsWrapped checks if an error is already wrapped by our custom error types

func LogBySeverity ¶ added in v0.9.0

func LogBySeverity(logger *slog.Logger, err *Error)

LogBySeverity logs an error using the appropriate slog level based on its severity

func RootCause ¶ added in v0.8.0

func RootCause(err error) error

func SetLocationCapture ¶ added in v0.9.0

func SetLocationCapture(enabled bool)

SetLocationCapture globally enables or disables location capture

func ToSlogAttributes ¶ added in v0.8.0

func ToSlogAttributes(err error) []slog.Attr

Types ¶

type BaseError ¶ added in v0.5.1

type BaseError = Error

type Category ¶

type Category string

Category represents a high level error category

const (
	CategoryValidation       Category = "validation"
	CategoryAuth             Category = "authentication"
	CategoryAuthz            Category = "authorization"
	CategoryOperation        Category = "operation"
	CategoryNotFound         Category = "not_found"
	CategoryConflict         Category = "conflict"
	CategoryRateLimit        Category = "rate_limit"
	CategoryBadInput         Category = "bad_input"
	CategoryInternal         Category = "internal"
	CategoryExternal         Category = "external"
	CategoryMiddleware       Category = "middleware"
	CategoryRouting          Category = "routing"
	CategoryHandler          Category = "handler"
	CategoryMethodNotAllowed Category = "method_not_allowed"
	CategoryCommand          Category = "command"
)

func HTTPStatusToCategory ¶ added in v0.3.0

func HTTPStatusToCategory(code int) Category

HTTPStatusToCategory maps HTTP status codes to error categories

func RootCategory ¶ added in v0.8.0

func RootCategory(err error) Category

func (Category) Extend ¶ added in v0.5.0

func (c Category) Extend(s string) Category

func (Category) String ¶ added in v0.3.0

func (c Category) String() string

type CollectorOption ¶ added in v0.9.0

type CollectorOption func(*ErrorCollector)

CollectorOption defines functional options for ErrorCollector configuration

func WithContext ¶ added in v0.9.0

func WithContext(ctx context.Context) CollectorOption

WithContext sets the context for the collector

func WithMaxErrors ¶ added in v0.9.0

func WithMaxErrors(max int) CollectorOption

WithMaxErrors sets the maximum number of errors to collect

func WithStrictMode ¶ added in v0.9.0

func WithStrictMode(strict bool) CollectorOption

WithStrictMode enables strict mode where the collector returns false when maximum errors are reached (instead of silently dropping errors)

type Error ¶

type Error struct {
	Category         Category         `json:"category"`
	Code             int              `json:"code,omitempty"`
	TextCode         string           `json:"text_code,omitempty"`
	Message          string           `json:"message"`
	Source           error            `json:"-"`
	ValidationErrors ValidationErrors `json:"validation_errors,omitempty"`
	Metadata         map[string]any   `json:"metadata,omitempty"`
	RequestID        string           `json:"request_id,omitempty"`
	Timestamp        time.Time        `json:"timestamp"`
	StackTrace       StackTrace       `json:"stack_trace,omitempty"`
	Location         *ErrorLocation   `json:"location,omitempty"`
	Severity         Severity         `json:"severity"`
}

func FromOzzoValidation ¶ added in v0.4.0

func FromOzzoValidation(err error, message string) *Error

func MapAuthErrors ¶ added in v0.3.0

func MapAuthErrors(err error) *Error

func MapHTTPErrors ¶ added in v0.3.0

func MapHTTPErrors(err error) *Error

func MapToError ¶ added in v0.2.0

func MapToError(err error, mappers []ErrorMapper) *Error

MapToError converts any error to our Error type using provided mappers

func New ¶

func New(message string, category ...Category) *Error

New creates a new Error with the specified category and message

func NewCritical ¶ added in v0.9.0

func NewCritical(message string, category Category) *Error

NewCritical creates a new Error with Critical severity

func NewDebug ¶ added in v0.9.0

func NewDebug(message string, category Category) *Error

NewDebug creates a new Error with Debug severity

func NewInfo ¶ added in v0.9.0

func NewInfo(message string, category Category) *Error

NewInfo creates a new Error with Info severity

func NewValidation ¶

func NewValidation(message string, fieldErrors ...FieldError) *Error

func NewValidationFromGroups ¶

func NewValidationFromGroups(message string, groups map[string][]string) *Error

func NewValidationFromMap ¶

func NewValidationFromMap(message string, fieldMap map[string]string) *Error

func NewWarning ¶ added in v0.9.0

func NewWarning(message string, category Category) *Error

NewWarning creates a new Error with Warning severity

func NewWithLocation ¶ added in v0.9.0

func NewWithLocation(message string, category Category, location *ErrorLocation) *Error

NewWithLocation creates a new Error with explicit location setting

func ValidateWithOzzo ¶ added in v0.4.0

func ValidateWithOzzo(validateFunc func() error, message string) *Error

func Wrap ¶

func Wrap(source error, category Category, message string) *Error

Wrap creates a new Error that wraps an existing error

func (*Error) AllValidationErrors ¶ added in v0.8.0

func (e *Error) AllValidationErrors() ValidationErrors

func (*Error) Clone ¶ added in v0.8.0

func (e *Error) Clone() *Error

func (*Error) Error ¶

func (e *Error) Error() string

func (*Error) ErrorWithStack ¶

func (e *Error) ErrorWithStack() string

func (*Error) GetLocation ¶ added in v0.9.0

func (e *Error) GetLocation() *ErrorLocation

GetLocation returns the location where the error occurred

func (*Error) GetSeverity ¶ added in v0.9.0

func (e *Error) GetSeverity() Severity

GetSeverity returns the severity level of the error

func (*Error) HasLocation ¶ added in v0.9.0

func (e *Error) HasLocation() bool

HasLocation returns true if the error has location information

func (*Error) HasSeverity ¶ added in v0.9.0

func (e *Error) HasSeverity(s Severity) bool

HasSeverity returns true if the error has the specified severity level

func (*Error) IsAboveSeverity ¶ added in v0.9.0

func (e *Error) IsAboveSeverity(threshold Severity) bool

IsAboveSeverity returns true if the error's severity is above the threshold

func (*Error) MarshalJSON ¶

func (e *Error) MarshalJSON() ([]byte, error)

func (*Error) ToErrorResponse ¶ added in v0.2.0

func (e *Error) ToErrorResponse(includeStack bool, stackTrace StackTrace) ErrorResponse

func (*Error) Unwrap ¶

func (e *Error) Unwrap() error

func (*Error) ValidationMap ¶ added in v0.6.0

func (e *Error) ValidationMap() map[string]string

ValidationMap returns validation errors as a map for easy template usage

func (*Error) WithCode ¶

func (e *Error) WithCode(code int) *Error

func (*Error) WithLocation ¶ added in v0.9.0

func (e *Error) WithLocation(loc *ErrorLocation) *Error

WithLocation sets the location where the error occurred

func (*Error) WithMetadata ¶

func (e *Error) WithMetadata(metas ...map[string]any) *Error

func (*Error) WithRequestID ¶

func (e *Error) WithRequestID(id string) *Error

TODO: either remove or rename to WithTraceID

func (*Error) WithSeverity ¶ added in v0.9.0

func (e *Error) WithSeverity(s Severity) *Error

WithSeverity sets the severity level of the error

func (*Error) WithStackTrace ¶

func (e *Error) WithStackTrace() *Error

func (*Error) WithTextCode ¶

func (e *Error) WithTextCode(code string) *Error

type ErrorCollector ¶ added in v0.9.0

type ErrorCollector struct {
	// contains filtered or unexported fields
}

ErrorCollector provides thread-safe collection and aggregation of errors for batch operations and complex error handling scenarios

func NewCollector ¶ added in v0.9.0

func NewCollector(opts ...CollectorOption) *ErrorCollector

NewCollector creates a new ErrorCollector with the provided options

func (*ErrorCollector) Add ¶ added in v0.9.0

func (c *ErrorCollector) Add(err error) bool

Add adds an error to the collector in a thread-safe manner Returns true if the error was added, false if the collector is full and operating in strict mode

func (*ErrorCollector) AddFieldErrors ¶ added in v0.9.0

func (c *ErrorCollector) AddFieldErrors(errors ...FieldError)

AddFieldErrors adds multiple field errors as a single validation error

func (*ErrorCollector) AddRetryable ¶ added in v0.9.0

func (c *ErrorCollector) AddRetryable(err error, category Category, message string)

AddRetryable adds a retryable error to the collector

func (*ErrorCollector) AddValidation ¶ added in v0.9.0

func (c *ErrorCollector) AddValidation(field, message string)

AddValidation adds a validation error for a specific field

func (*ErrorCollector) CategoryStats ¶ added in v0.9.0

func (c *ErrorCollector) CategoryStats() map[Category]int

CategoryStats returns the count of errors by category

func (*ErrorCollector) Count ¶ added in v0.9.0

func (c *ErrorCollector) Count() int

Count returns the number of errors currently in the collector

func (*ErrorCollector) Errors ¶ added in v0.9.0

func (c *ErrorCollector) Errors() []*Error

Errors returns a copy of all errors in the collector

func (*ErrorCollector) FilterByCategory ¶ added in v0.9.0

func (c *ErrorCollector) FilterByCategory(cat Category) []*Error

FilterByCategory returns all errors matching the specified category

func (*ErrorCollector) FilterBySeverity ¶ added in v0.9.0

func (c *ErrorCollector) FilterBySeverity(min Severity) []*Error

FilterBySeverity returns all errors with severity at or above the specified minimum

func (*ErrorCollector) GetAllValidationErrors ¶ added in v0.9.0

func (c *ErrorCollector) GetAllValidationErrors() ValidationErrors

GetAllValidationErrors aggregates all validation errors from all collected errors This includes both direct validation errors and validation errors from wrapped errors

func (*ErrorCollector) GetRetryableErrors ¶ added in v0.9.0

func (c *ErrorCollector) GetRetryableErrors() []*Error

GetRetryableErrors returns all errors that could be considered retryable based on their severity level (errors below Critical severity)

func (*ErrorCollector) GetValidationErrors ¶ added in v0.9.0

func (c *ErrorCollector) GetValidationErrors() ValidationErrors

GetValidationErrors aggregates all validation errors from collected errors

func (*ErrorCollector) HasErrors ¶ added in v0.9.0

func (c *ErrorCollector) HasErrors() bool

HasErrors returns true if the collector contains any errors

func (*ErrorCollector) HasRetryableErrors ¶ added in v0.9.0

func (c *ErrorCollector) HasRetryableErrors() bool

HasRetryableErrors returns true if any collected errors are retryable

func (*ErrorCollector) LogErrors ¶ added in v0.9.0

func (c *ErrorCollector) LogErrors(logger *slog.Logger)

LogErrors logs all collected errors using the provided logger Each error is logged individually with its appropriate severity level

func (*ErrorCollector) Merge ¶ added in v0.9.0

func (c *ErrorCollector) Merge() *Error

Merge creates a single aggregate error from all collected errors Returns nil if no errors have been collected

func (*ErrorCollector) MostCommonCategory ¶ added in v0.9.0

func (c *ErrorCollector) MostCommonCategory() Category

MostCommonCategory returns the category with the highest error count

func (*ErrorCollector) Reset ¶ added in v0.9.0

func (c *ErrorCollector) Reset()

Reset clears all errors from the collector

func (*ErrorCollector) SeverityDistribution ¶ added in v0.9.0

func (c *ErrorCollector) SeverityDistribution() map[Severity]int

SeverityDistribution returns the count of errors by severity level

func (*ErrorCollector) ToErrorResponse ¶ added in v0.9.0

func (c *ErrorCollector) ToErrorResponse(includeStack bool) *ErrorResponse

ToErrorResponse converts the collector's state to an HTTP error response If the collector has no errors, returns nil If the collector has exactly one error, returns that error's response If the collector has multiple errors, returns a merged error response

func (*ErrorCollector) ToSlogAttributes ¶ added in v0.9.0

func (c *ErrorCollector) ToSlogAttributes() []slog.Attr

ToSlogAttributes creates slog attributes for the collector's current state Includes error count, context information, and category/severity statistics

type ErrorLocation ¶ added in v0.9.0

type ErrorLocation struct {
	File     string `json:"file"`
	Line     int    `json:"line"`
	Function string `json:"function"`
}

ErrorLocation represents the file, line, and function where an error was created

func Here ¶ added in v0.9.0

func Here() *ErrorLocation

Here captures the location where this function is called This is a convenience function for explicit location capture

func (*ErrorLocation) String ¶ added in v0.9.0

func (loc *ErrorLocation) String() string

String returns a formatted string representation of the location

type ErrorMapper ¶ added in v0.2.0

type ErrorMapper func(error) *Error

ErrorMapper is a function that can map specific error types to our Error type

func DefaultErrorMappers ¶ added in v0.3.0

func DefaultErrorMappers() []ErrorMapper

type ErrorResponse ¶ added in v0.2.0

type ErrorResponse struct {
	Error *Error `json:"error"`
}

ErrorResponse represents the standard structure for API error responses

type FieldError ¶

type FieldError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
	Value   any    `json:"value,omitempty"`
}

FieldError reprents a single validation error for a given field

func (FieldError) Error ¶

func (e FieldError) Error() string

type LocationConfig ¶ added in v0.9.0

type LocationConfig struct {
	// EnableLocationCapture controls whether error locations are captured
	EnableLocationCapture bool
}

LocationConfig holds configuration for location capture behavior

type RetryableError ¶ added in v0.5.0

type RetryableError struct {
	*BaseError
	// contains filtered or unexported fields
}

RetryableError extends Error with retry functionality

func NewNonRetryable ¶ added in v0.5.0

func NewNonRetryable(message string, category Category) *RetryableError

NewNonRetryable creates a non-retryable error (useful for validation, auth, etc.)

func NewRetryable ¶ added in v0.5.0

func NewRetryable(message string, category Category) *RetryableError

func NewRetryableExternal ¶ added in v0.5.0

func NewRetryableExternal(message string) *RetryableError

NewRetryableExternal creates a retryable error for an external service

func NewRetryableOperation ¶ added in v0.5.0

func NewRetryableOperation(message string, delay ...time.Duration) *RetryableError

NewRetryableOperation creates a retryable error for operation failures with a short delay of 500 millis by default

func WrapRetryable ¶ added in v0.5.0

func WrapRetryable(source error, category Category, message string) *RetryableError

func (*RetryableError) Error ¶ added in v0.5.1

func (r *RetryableError) Error() string

func (*RetryableError) IsRetryable ¶ added in v0.5.0

func (r *RetryableError) IsRetryable() bool

IsRetryable returns whether this error should trigger a retry Critical and Fatal errors are never retryable regardless of the retryable flag

func (*RetryableError) RetryDealy ¶ added in v0.5.0

func (r *RetryableError) RetryDealy(attempt int) time.Duration

RetryDelay calculates the delay before the next retry attempt Uses exponential backoff: baseDelay * (2^(attempt-1))

func (*RetryableError) WithCode ¶ added in v0.5.0

func (r *RetryableError) WithCode(code int) *RetryableError

func (*RetryableError) WithLocation ¶ added in v0.9.0

func (r *RetryableError) WithLocation(loc *ErrorLocation) *RetryableError

WithLocation sets the location where the error occurred

func (*RetryableError) WithMetadata ¶ added in v0.5.0

func (r *RetryableError) WithMetadata(metas ...map[string]any) *RetryableError

func (*RetryableError) WithRetryDelay ¶ added in v0.5.0

func (r *RetryableError) WithRetryDelay(delay time.Duration) *RetryableError

WithRetryDelay sets the base delay for retry attempts

func (*RetryableError) WithRetryable ¶ added in v0.5.0

func (r *RetryableError) WithRetryable(retryable bool) *RetryableError

WithRetryable sets whether this error should be retryable

func (*RetryableError) WithSeverity ¶ added in v0.9.0

func (r *RetryableError) WithSeverity(s Severity) *RetryableError

WithSeverity sets the severity level of the retryable error

func (*RetryableError) WithStackTrace ¶ added in v0.5.0

func (r *RetryableError) WithStackTrace() *RetryableError

func (*RetryableError) WithTextCode ¶ added in v0.5.0

func (r *RetryableError) WithTextCode(code string) *RetryableError

type Severity ¶ added in v0.9.0

type Severity int

Severity represents the severity level of an error

const (
	SeverityDebug Severity = iota
	SeverityInfo
	SeverityWarning
	SeverityError
	SeverityCritical
	SeverityFatal
)

func (Severity) MarshalJSON ¶ added in v0.9.0

func (s Severity) MarshalJSON() ([]byte, error)

MarshalJSON implements JSON marshaling for Severity

func (Severity) String ¶ added in v0.9.0

func (s Severity) String() string

String returns the string representation of the severity level

func (*Severity) UnmarshalJSON ¶ added in v0.9.0

func (s *Severity) UnmarshalJSON(data []byte) error

UnmarshalJSON implements JSON unmarshaling for Severity

type StackFrame ¶

type StackFrame struct {
	Function string `json:"function"`
	File     string `json:"file"`
	Line     int    `json:"line"`
}

StackFrame is a single frame in the stack trace

type StackTrace ¶

type StackTrace []StackFrame

StackTrace is a collection of stack frames

func CaptureStackTrace ¶

func CaptureStackTrace(skip int) StackTrace

func (StackTrace) String ¶

func (s StackTrace) String() string

type ValidationErrors ¶

type ValidationErrors []FieldError

ValidationErrors is a collection of field level validation errors

func GetValidationErrors ¶

func GetValidationErrors(err error) (ValidationErrors, bool)

func (ValidationErrors) Error ¶

func (e ValidationErrors) Error() string

Jump to

Keyboard shortcuts

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