Feature description:
Include each violation in the message of ValidationError, the way protovalidate-go does, rather than only invalid <MessageName>.
Problem it solves or use case:
str(ValidationError) is invalid <MessageName>, so logs and RPC error messages don't say which field failed or why:
>>> protovalidate.validate(CreateUserRequest(user=User(email="x")))
protovalidate.ValidationError: invalid CreateUserRequest
This has been the message since validate() was added in #32, and both the protobuf-py port (#482) and the native extension (#507) kept it unchanged. The details are only available by inspecting violations or to_proto().
I'm looking at building a protovalidate interceptor for connect-py, the Python counterpart to connectrpc/validate-go. validate-go uses the validation error's message as the Connect error message (connect.Errorf(code, "%s", err.Error())), so Go clients see which fields failed, while Python clients only see invalid CreateUserRequest.
I realize this can be stitched together without this changing here from the exported API, but it seems like a valuable improvement to the default behavior?
Proposed implementation or solution:
Use protovalidate-go's format: ValidationError.Error() gives validation error: <violation> for one violation, or validation errors: followed by \n - <violation> for each when there are several. Each violation is rendered as <field path>: <message>, falling back to [<rule id>] when there's no message. For the example above:
validation error: user.email: must be a valid email address
The violations already carry field, message and rule_id, so only the message string built in Validator.validate (src/lib.rs) would change. Code that matches on the exact invalid <MessageName> text would break, so this may warrant a release note.
Examples or references:
Feature description:
Include each violation in the message of
ValidationError, the way protovalidate-go does, rather than onlyinvalid <MessageName>.Problem it solves or use case:
str(ValidationError)isinvalid <MessageName>, so logs and RPC error messages don't say which field failed or why:This has been the message since
validate()was added in #32, and both the protobuf-py port (#482) and the native extension (#507) kept it unchanged. The details are only available by inspectingviolationsorto_proto().I'm looking at building a protovalidate interceptor for connect-py, the Python counterpart to connectrpc/validate-go. validate-go uses the validation error's message as the Connect error message (
connect.Errorf(code, "%s", err.Error())), so Go clients see which fields failed, while Python clients only seeinvalid CreateUserRequest.I realize this can be stitched together without this changing here from the exported API, but it seems like a valuable improvement to the default behavior?
Proposed implementation or solution:
Use protovalidate-go's format:
ValidationError.Error()givesvalidation error: <violation>for one violation, orvalidation errors:followed by\n - <violation>for each when there are several. Each violation is rendered as<field path>: <message>, falling back to[<rule id>]when there's no message. For the example above:The violations already carry
field,messageandrule_id, so only the message string built inValidator.validate(src/lib.rs) would change. Code that matches on the exactinvalid <MessageName>text would break, so this may warrant a release note.Examples or references:
ValidationError.ErrorandViolation.String