-
-
Notifications
You must be signed in to change notification settings - Fork 251
Open
Description
Problem
When consuming validation errors from huma, only a human-readable message string is available on each ErrorDetail. This makes it difficult to programmatically map huma errors to custom application error types without fragile string parsing.
For example, an expected_one_of error today looks like:
{
"message": "expected value to be one of \"foo\", \"bar\"",
"location": "body.status",
"value": "baz"
}To handle this in downstream code you'd have to parse the message string to
recover the allowed values — which breaks if the message format changes or is
customised via ErrorFormatter.
Solution
Add two new omitempty fields to ErrorDetail:
- Code string — a snake_case machine-readable identifier (e.g. "expected_one_of") that corresponds to one of the new validation.Code* constants, one per existing Msg* variable.
- Params map[string]any — the constraint parameters relevant to the error, e.g. {"allowed": ["foo","bar"]} for enum errors or {"min": 3} for min-length errors.
The same error now looks like:
{
"message": "expected value to be one of \"foo\", \"bar\"",
"location": "body.status",
"value": "baz",
"code": "expected_one_of",
"params": { "allowed": ["foo", "bar"] }
}This enables downstream consumers to switch on Code without touching Message:
for _, detail := range errModel.Errors {
switch detail.Code {
case validation.CodeExpectedOneOf:
allowed := detail.Params["allowed"].([]any)
// map to your own enum error with structured allowed values
case validation.CodeExpectedRequiredProperty:
prop := detail.Params["property"].(string)
// map to your own missing-field error
}
}Changes
- validation/messages.go — adds a Code* constant for every Msg* variable
- error.go — adds Code string and Params map[string]any to ErrorDetail (both omitempty, fully backwards-compatible)
- validate.go — adds ValidateResult.AddCode() method; migrates all internal res.Add() call sites to res.AddCode() with the appropriate code and params
- validate_test.go — adds TestValidateErrorCodes with 43 subtests covering every code and verifying params where applicable
Backwards compatibility
- The two new fields are omitempty — existing JSON consumers see no change unless they opt in to reading the new fields.
- ValidateResult.Add() and ValidateResult.Addf() are unchanged.
- Custom NewError implementations continue to work as before.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels