summaryrefslogtreecommitdiff
path: root/internal/errors/errors.go
blob: 3fa3e67d739b6d4b47e38d736bafc38f600d2466 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Package errors provides comprehensive error handling utilities for DTail.
// It defines sentinel errors for common error conditions, error wrapping
// functions for adding context, and multi-error support for operations
// that can encounter multiple failures.
//
// Key features:
// - Predefined sentinel errors for common DTail error conditions
// - Error wrapping with context for better debugging
// - Multi-error support for batch operations
// - Standard error interface compatibility
// - Error type checking and unwrapping utilities
//
// Error categories:
// - Connection: Network and SSH connection errors
// - Authentication: Permission and credential errors
// - Configuration: Config parsing and validation errors
// - File/IO: File system access and operation errors
// - Protocol: Communication protocol errors
// - Resource: Resource exhaustion and timeout errors
//
// This package enables consistent error handling across the DTail codebase
// and provides clear error categorization for troubleshooting.
package errors

import (
	"errors"
	"fmt"
)

// Sentinel errors for common error conditions
var (
	// Connection errors
	ErrConnectionFailed    = errors.New("connection failed")
	ErrConnectionTimeout   = errors.New("connection timeout")
	ErrConnectionRefused   = errors.New("connection refused")
	ErrTooManyConnections  = errors.New("too many connections")
	
	// Authentication/Permission errors
	ErrPermissionDenied    = errors.New("permission denied")
	ErrAuthenticationFailed = errors.New("authentication failed")
	ErrUnauthorized        = errors.New("unauthorized")
	ErrInvalidCredentials  = errors.New("invalid credentials")
	
	// Configuration errors
	ErrInvalidConfig       = errors.New("invalid configuration")
	ErrMissingConfig       = errors.New("missing configuration")
	ErrConfigValidation    = errors.New("configuration validation failed")
	
	// File/IO errors
	ErrFileNotFound        = errors.New("file not found")
	ErrFileAccessDenied    = errors.New("file access denied")
	ErrInvalidPath         = errors.New("invalid path")
	ErrReadFailed          = errors.New("read failed")
	ErrWriteFailed         = errors.New("write failed")
	
	// Protocol errors
	ErrInvalidProtocol     = errors.New("invalid protocol")
	ErrProtocolMismatch    = errors.New("protocol version mismatch")
	ErrInvalidCommand      = errors.New("invalid command")
	ErrInvalidQuery        = errors.New("invalid query")
	
	// Resource errors
	ErrResourceExhausted   = errors.New("resource exhausted")
	ErrBufferFull          = errors.New("buffer full")
	ErrTimeout             = errors.New("operation timeout")
	
	// General errors
	ErrInvalidArgument     = errors.New("invalid argument")
	ErrNotImplemented      = errors.New("not implemented")
	ErrInternal            = errors.New("internal error")
)

// Error wrapping functions

// Wrap wraps an error with additional context
func Wrap(err error, msg string) error {
	if err == nil {
		return nil
	}
	return fmt.Errorf("%s: %w", msg, err)
}

// Wrapf wraps an error with formatted context
func Wrapf(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}
	return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)
}

// New creates a new error with formatted message
func New(format string, args ...interface{}) error {
	return fmt.Errorf(format, args...)
}

// Is checks if an error is of a specific type
func Is(err, target error) bool {
	return errors.Is(err, target)
}

// As attempts to extract a specific error type
func As(err error, target interface{}) bool {
	return errors.As(err, target)
}

// Unwrap returns the wrapped error
func Unwrap(err error) error {
	return errors.Unwrap(err)
}

// Multi-error support for operations that can have multiple failures

// MultiError represents multiple errors
type MultiError struct {
	errors []error
}

// NewMultiError creates a new MultiError
func NewMultiError() *MultiError {
	return &MultiError{
		errors: make([]error, 0),
	}
}

// Add adds an error to the MultiError
func (m *MultiError) Add(err error) {
	if err != nil {
		m.errors = append(m.errors, err)
	}
}

// HasErrors returns true if there are any errors
func (m *MultiError) HasErrors() bool {
	return len(m.errors) > 0
}

// Error implements the error interface
func (m *MultiError) Error() string {
	if len(m.errors) == 0 {
		return ""
	}
	if len(m.errors) == 1 {
		return m.errors[0].Error()
	}
	return fmt.Sprintf("multiple errors occurred: %v", m.errors)
}

// Errors returns all collected errors
func (m *MultiError) Errors() []error {
	return m.errors
}

// ErrorOrNil returns nil if no errors, otherwise returns the MultiError
func (m *MultiError) ErrorOrNil() error {
	if m.HasErrors() {
		return m
	}
	return nil
}