domains / / kubeflow/kubeflow
Contextualize and classify errors
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.
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:
- Use early returns with clear error checks:
if err != nil { // Log error and/or return response return nil, fmt.Errorf("failed to process request: %v", err) } // Handle the success case - Provide context in error messages:
// 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)) } - Distinguish between error variables in nested scopes:
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 } - Classify errors properly: ```go // For user input errors return &kfapis.KfError{ Code: int(kfapis.INVALID_ARGUMENT), Message: fmt.Sprintf(“Project not specified: %v”, err), }
// 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),
}
}