Always provide meaningful context when handling errors, and classify them appropriately based on their source. This improves debugging, helps users understand issues, and creates a consistent approach to error handling across the codebase.
Follow these error handling principles:
if err != nil {
// Log error and/or return response
return nil, fmt.Errorf("failed to process request: %v", err)
}
// Handle the success case
// Instead of just returning or logging the raw error
if _, err := w.Write([]byte(err.Error())); err != nil {
log.Error(err) // Poor context
// Better approach with context
log.Error(fmt.Errorf("failed to write error response: %v", err))
}
err := json.NewDecoder(r.Body).Decode(&profile)
if err != nil {
// Handle first error
if writeErr := json.NewEncoder(w).Encode(err); writeErr != nil {
log.Error(fmt.Errorf("decode failed: %v, response write failed: %v", err, writeErr))
}
return
}
// For system/internal errors return &kfapis.KfError{ Code: int(kfapis.INTERNAL_ERROR), Message: fmt.Sprintf(“Failed to create application: %v”, err), }
5. **Use consistent error types** throughout your codebase, and consider creating helper functions to reduce boilerplate:
```go
func NewInvalidArgumentError(err error, msg string) *kfapis.KfError {
return &kfapis.KfError{
Code: int(kfapis.INVALID_ARGUMENT),
Message: fmt.Sprintf("%s: %v", msg, err),
}
}
Enter the URL of a public GitHub repository