Errors
The CPE library provides a comprehensive error handling system with structured error types for different failure scenarios.
Error Types
ErrorType
type ErrorType int
const (
ErrorTypeParsingFailed ErrorType = iota // Parsing operation failed
ErrorTypeInvalidFormat // Invalid format detected
ErrorTypeInvalidPart // Invalid part value
ErrorTypeInvalidAttribute // Invalid attribute value
ErrorTypeNotFound // Resource not found
ErrorTypeOperationFailed // General operation failure
)
Enumeration of different error types that can occur in the library.
CPEError
type CPEError struct {
Type ErrorType // Error type classification
Message string // Human-readable error message
CPEString string // Related CPE string (if applicable)
Err error // Underlying error (if any)
}
The main error type used throughout the library, providing structured error information.
Methods
Error
func (e *CPEError) Error() string
Implements the error
interface, returning a formatted error message.
Returns:
string
- Formatted error message
Example:
err := cpe.NewInvalidFormatError("invalid:cpe:format")
fmt.Printf("Error: %s\n", err.Error())
// Output: invalid CPE format: invalid:cpe:format
Unwrap
func (e *CPEError) Unwrap() error
Returns the underlying error for error chain unwrapping.
Returns:
error
- Underlying error ornil
Example:
originalErr := errors.New("underlying issue")
cpeErr := cpe.NewOperationFailedError("parse", originalErr)
unwrapped := cpeErr.Unwrap()
fmt.Printf("Underlying error: %v\n", unwrapped)
Error Constructors
NewParsingError
func NewParsingError(cpeString string, err error) *CPEError
Creates a parsing error for when CPE string parsing fails.
Parameters:
cpeString
- The CPE string that failed to parseerr
- Underlying parsing error
Returns:
*CPEError
- Parsing error
Example:
err := cpe.NewParsingError("invalid:format", errors.New("malformed string"))
fmt.Printf("Parsing error: %v\n", err)
NewInvalidFormatError
func NewInvalidFormatError(cpeString string) *CPEError
Creates an error for invalid CPE format.
Parameters:
cpeString
- The invalid CPE string
Returns:
*CPEError
- Invalid format error
Example:
err := cpe.NewInvalidFormatError("not:a:valid:cpe")
fmt.Printf("Format error: %v\n", err)
NewInvalidPartError
func NewInvalidPartError(part string) *CPEError
Creates an error for invalid CPE part values.
Parameters:
part
- The invalid part value
Returns:
*CPEError
- Invalid part error
Example:
err := cpe.NewInvalidPartError("x") // Valid parts are "a", "h", "o"
fmt.Printf("Part error: %v\n", err)
NewInvalidAttributeError
func NewInvalidAttributeError(attribute, value string) *CPEError
Creates an error for invalid attribute values.
Parameters:
attribute
- Name of the invalid attributevalue
- The invalid value
Returns:
*CPEError
- Invalid attribute error
Example:
err := cpe.NewInvalidAttributeError("vendor", "invalid\x00vendor")
fmt.Printf("Attribute error: %v\n", err)
NewNotFoundError
func NewNotFoundError(what string) *CPEError
Creates an error for when a resource is not found.
Parameters:
what
- Description of what was not found
Returns:
*CPEError
- Not found error
Example:
err := cpe.NewNotFoundError("CPE dictionary")
fmt.Printf("Not found error: %v\n", err)
NewOperationFailedError
func NewOperationFailedError(operation string, err error) *CPEError
Creates an error for when an operation fails.
Parameters:
operation
- Name of the failed operationerr
- Underlying error
Returns:
*CPEError
- Operation failed error
Example:
err := cpe.NewOperationFailedError("download", errors.New("network timeout"))
fmt.Printf("Operation error: %v\n", err)
Error Checking Functions
IsParsingError
func IsParsingError(err error) bool
Checks if an error is a parsing error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's a parsing error
Example:
_, err := cpe.ParseCpe23("invalid:format")
if cpe.IsParsingError(err) {
fmt.Println("This is a parsing error")
}
IsInvalidFormatError
func IsInvalidFormatError(err error) bool
Checks if an error is an invalid format error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's an invalid format error
IsInvalidPartError
func IsInvalidPartError(err error) bool
Checks if an error is an invalid part error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's an invalid part error
IsInvalidAttributeError
func IsInvalidAttributeError(err error) bool
Checks if an error is an invalid attribute error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's an invalid attribute error
IsNotFoundError
func IsNotFoundError(err error) bool
Checks if an error is a not found error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's a not found error
IsOperationFailedError
func IsOperationFailedError(err error) bool
Checks if an error is an operation failed error.
Parameters:
err
- Error to check
Returns:
bool
-true
if it's an operation failed error
Storage Errors
The library also defines standard storage errors:
var (
ErrNotFound = errors.New("record not found")
ErrDuplicate = errors.New("duplicate record")
ErrInvalidData = errors.New("invalid data")
ErrStorageDisconnected = errors.New("storage is disconnected")
)
These can be used with errors.Is()
for checking:
Example:
cpe, err := storage.RetrieveCPE("non-existent")
if errors.Is(err, cpe.ErrNotFound) {
fmt.Println("CPE not found in storage")
}
Error Handling Patterns
Basic Error Handling
// Parse CPE and handle errors
cpeObj, err := cpe.ParseCpe23("invalid:format")
if err != nil {
if cpe.IsInvalidFormatError(err) {
fmt.Println("Invalid CPE format provided")
} else {
fmt.Printf("Other parsing error: %v\n", err)
}
return
}
Detailed Error Information
// Get detailed error information
_, err := cpe.ParseCpe23("cpe:2.3:x:vendor:product:1.0:*:*:*:*:*:*:*")
if err != nil {
if cpeErr, ok := err.(*cpe.CPEError); ok {
fmt.Printf("Error type: %d\n", cpeErr.Type)
fmt.Printf("Message: %s\n", cpeErr.Message)
fmt.Printf("CPE string: %s\n", cpeErr.CPEString)
if cpeErr.Err != nil {
fmt.Printf("Underlying error: %v\n", cpeErr.Err)
}
}
}
Error Chain Unwrapping
// Handle error chains
err := someComplexOperation()
if err != nil {
// Check for specific error types in the chain
var cpeErr *cpe.CPEError
if errors.As(err, &cpeErr) {
fmt.Printf("CPE error found: %s\n", cpeErr.Message)
}
// Check for storage errors
if errors.Is(err, cpe.ErrNotFound) {
fmt.Println("Resource not found")
}
}
Comprehensive Error Handling
func handleCPEOperation(cpeString string) {
cpeObj, err := cpe.ParseCpe23(cpeString)
if err != nil {
switch {
case cpe.IsInvalidFormatError(err):
fmt.Printf("Invalid format: %s\n", cpeString)
case cpe.IsInvalidPartError(err):
fmt.Printf("Invalid part in: %s\n", cpeString)
case cpe.IsParsingError(err):
fmt.Printf("General parsing error: %v\n", err)
default:
fmt.Printf("Unexpected error: %v\n", err)
}
return
}
// Use the parsed CPE
fmt.Printf("Successfully parsed: %s\n", cpeObj.GetURI())
}
Complete Example
package main
import (
"errors"
"fmt"
"github.com/scagogogo/cpe"
)
func main() {
// Test different error scenarios
fmt.Println("=== Error Handling Examples ===")
// Invalid format error
fmt.Println("\n1. Invalid Format Error:")
_, err := cpe.ParseCpe23("invalid:format")
if err != nil {
if cpe.IsInvalidFormatError(err) {
fmt.Printf("✓ Detected invalid format error: %v\n", err)
}
}
// Invalid part error
fmt.Println("\n2. Invalid Part Error:")
_, err = cpe.ParseCpe23("cpe:2.3:x:vendor:product:1.0:*:*:*:*:*:*:*")
if err != nil {
if cpe.IsInvalidPartError(err) {
fmt.Printf("✓ Detected invalid part error: %v\n", err)
}
}
// Storage error simulation
fmt.Println("\n3. Storage Error:")
storage := cpe.NewMemoryStorage()
storage.Initialize()
_, err = storage.RetrieveCPE("non-existent-cpe")
if err != nil {
if errors.Is(err, cpe.ErrNotFound) {
fmt.Printf("✓ Detected not found error: %v\n", err)
}
}
// Detailed error information
fmt.Println("\n4. Detailed Error Information:")
_, err = cpe.ParseCpe23("cpe:2.3:invalid:vendor:product:1.0:*:*:*:*:*:*:*")
if err != nil {
if cpeErr, ok := err.(*cpe.CPEError); ok {
fmt.Printf("Error Type: %d\n", cpeErr.Type)
fmt.Printf("Message: %s\n", cpeErr.Message)
fmt.Printf("CPE String: %s\n", cpeErr.CPEString)
}
}
// Error type checking
fmt.Println("\n5. Error Type Checking:")
testCases := []struct {
input string
description string
}{
{"invalid", "completely invalid"},
{"cpe:2.3:x:vendor:product:1.0:*:*:*:*:*:*:*", "invalid part"},
{"cpe:2.3:a:vendor:product", "too few components"},
}
for _, tc := range testCases {
_, err := cpe.ParseCpe23(tc.input)
if err != nil {
fmt.Printf("Input: %s (%s)\n", tc.input, tc.description)
switch {
case cpe.IsInvalidFormatError(err):
fmt.Println(" → Invalid format error")
case cpe.IsInvalidPartError(err):
fmt.Println(" → Invalid part error")
case cpe.IsParsingError(err):
fmt.Println(" → General parsing error")
default:
fmt.Println(" → Other error type")
}
}
}
// Successful operation
fmt.Println("\n6. Successful Operation:")
cpeObj, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
fmt.Printf("Unexpected error: %v\n", err)
} else {
fmt.Printf("✓ Successfully parsed: %s\n", cpeObj.GetURI())
}
}