-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Description
Problem
The current FieldMask.IsValid(m proto.Message) bool method only returns a boolean indicating whether all paths are valid, but provides no information about which specific paths are invalid. This makes it difficult for developers to:
- Debug invalid field masks - developers have to manually inspect each path to determine which ones are causing validation failures
- Provide meaningful error messages - applications cannot give users specific feedback about which fields are problematic
- Implement incremental fixes - when working with complex field masks, it's hard to identify and fix invalid paths one by one
Proposed Solution
Add a new method GetInvalidPaths(m proto.Message) []string to the FieldMask type that returns a list of invalid paths.
// GetInvalidPaths returns a slice of paths that are invalid for the given message type.
// Returns an empty slice if all paths are valid.
func (x *FieldMask) GetInvalidPaths(m proto.Message) []stringUse Cases
API Validation with Detailed Error Messages
Current Problem - No way to identify which specific paths are invalid:
req.Msg.FieldMask.Normalize()
if !req.Msg.FieldMask.IsValid(req.Msg) {
// ❌ Can only return generic error - no way to tell user which paths are wrong
return status.Error(codes.InvalidArgument, "invalid field mask")
}With GetInvalidPaths - Provide specific feedback:
req.Msg.FieldMask.Normalize()
if invalidPaths := req.Msg.FieldMask.GetInvalidPaths(req.Msg); len(invalidPaths) > 0 {
// ✅ Tell user exactly which paths are problematic
return status.Errorf(codes.InvalidArgument,
"invalid field mask paths: %v", invalidPaths)
// Error: "invalid field mask paths: [user.invalid_field, metadata.bad_path]"
}Implementation
The implementation would reuse the existing numValidPaths function internally:
func (x *FieldMask) GetInvalidPaths(m proto.Message) []string {
if x == nil {
return nil
}
paths := x.GetPaths()
numValid := numValidPaths(m, paths)
if numValid == len(paths) {
return nil // all paths are valid
}
// Return the invalid paths (from numValid index onwards)
invalidPaths := make([]string, len(paths)-numValid)
copy(invalidPaths, paths[numValid:])
return invalidPaths
}Benefits
- Zero Breaking Changes - This is a pure addition that doesn't modify existing behavior
- Consistent with Existing Patterns - Follows the same validation logic as
IsValidandAppend - Minimal Performance Impact - Reuses existing validation logic, no additional reflection
- Developer Experience - Significantly improves debugging and error reporting capabilities
- Simple API - Clean, intuitive method signature that's easy to use
Alternatives Considered
- Modify
IsValidto return detailed information - Would break existing API - Add a separate validation result struct - More complex API for the common use case
- Use
Appendwith empty paths - Workaround that's not intuitive and doesn't provide all invalid paths
Backward Compatibility
This change is fully backward compatible as it only adds a new method without modifying existing functionality.
advdv
Metadata
Metadata
Assignees
Labels
No labels