fix: surface 422 validation error messages in SendDraft and UpdateDraft - #133
Conversation
There was a problem hiding this comment.
Pull request overview
Surfaces HEY API validation details from 422 responses in draft operations.
Changes:
- Parses
JSON422errors inUpdateDraftandSendDraft. - Returns validation messages to callers.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Suppressed comments (2)
go/pkg/hey/messages.go:234
- This branch bypasses
CheckResponsebut only sets the code and message, so parsed 422 errors now reportHTTPStatus == 0and drop the response'sX-Request-Id. That breaks the structured validation-error contract asserted inconformance/tests/error-mapping.json:64and the request-ID handling inhelpers.go:24-41. Construct the standard validation error and preserve the request ID.
return &Error{
Code: CodeValidation,
Message: strings.Join(resp.JSON422.Errors, ", "),
}
go/pkg/hey/messages.go:277
- As in
UpdateDraft, this manually constructed error loses the actual 422 status and request ID becauseCheckResponseis skipped. Callers inspectingError.HTTPStatusreceive zero even though the server returned 422; use the shared validation constructor and copy the response request ID.
return &Error{
Code: CodeValidation,
Message: strings.Join(resp.JSON422.Errors, ", "),
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
When HEY returns HTTP 422 with validation errors in the response body, the SDK currently discards them and returns a generic 'validation error'. Parse the JSON422 body and return the specific error messages so callers can show the user what went wrong.
Same fix as UpdateDraft: parse JSON422 body and return specific validation error messages instead of a generic 'validation error' string.
A parsed 422 body is the message, but the error it became dropped the HTTP status and the X-Request-Id that CheckResponse puts on every other status, so a caller inspecting HTTPStatus saw zero for a request the server refused. draftWriteError builds the error through ErrValidation and copies the request id, falling back to the body's message when it carries no errors list, and the bodyless 422 still maps by status. Tests cover UpdateDraft and SendDraft with a reasons list, and a 422 with no body at all.
The Go and Rust runners both dispatch UpdateDraft and SendDraft through the HEY layer, so a case that answers one with a reasons list and asserts the code, status, retryability and request id holds both SDKs to the same contract. Against the wrapper that returned a bare error with the reasons and nothing else, both cases fail.
7f51159 to
cdae58e
Compare
|
Rebased onto main and pushed two commits on top. 4bdeb63 keeps the structured error contract on the parsed 422: the error built from the reasons list dropped the HTTP status and the X-Request-Id that CheckResponse puts on every other status, so a caller inspecting HTTPStatus saw zero for a request the server refused. cdae58e adds the conformance case: both runners dispatch UpdateDraft and SendDraft through the HEY layer, so a 422 with a reasons list asserting code, status, retryability and request id holds Go and Rust to the same contract — against the wrapper as first pushed, both cases fail; with the fix they pass, and Rust already passed since its transport maps every 422 this way.
|
The generated client parses 422 responses into JSON422, but the service wrappers (UpdateDraft and SendDraft) discarded this and fell back to CheckResponse which returns a generic validation error string. Parse JSON422 and return specific messages from the response body instead.
Summary by cubic
UpdateDraftandSendDraftnow return the specific validation error messages from HEY API 422 responses instead of a generic "validation error" string. The error keeps the HTTP status and X-Request-Id, and falls back to the generic message when the response body carries no reasons.Written for commit cdae58e. Summary will update on new commits.