feat(errors): Error400.details.errors[] array for multi-field validation - #764
Conversation
Replace singular `details.field`/`details.constraint` with a typed
`details.errors[]` array so submit endpoints (POST /customers, PATCH
/customers/{id}) can report every invalid field in one round-trip.
Adds `FieldError` schema — one entry per invalid field, carrying
`field` (dot-notation path), optional `constraint` (FieldConstraint —
the existing machine-readable validator hint), and optional `message`
(human-readable explanation).
Backwards-incompatible change to `Error400.details`: the singular
`field` and `constraint` properties are removed. Approved per
lightsparkdev/webdev#31110 review — no consumers of the previous shape
had wired it into production yet.
Consumers of this shape land in webdev#31110.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript ✅ grid-ruby studio · code
|
| errors: | ||
| type: array | ||
| description: >- | ||
| Dot-notation path to the offending field. Present on field-validation | ||
| errors from submit endpoints. | ||
| example: taxIdentifier | ||
| constraint: | ||
| $ref: ./FieldConstraint.yaml | ||
| One entry per invalid field. Present on field-validation errors from | ||
| submit endpoints. | ||
| items: | ||
| $ref: ./FieldError.yaml |
There was a problem hiding this comment.
Obsolete Error400 test fixture
The only repository test for Error400.details still constructs and asserts the removed { field: "email" } shape, so it provides no regression coverage for parsing the new errors array and nested FieldError properties. Update the fixture and assertion alongside this contract change.
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/errors/Error400.yaml
Line: 107-113
Comment:
**Obsolete Error400 test fixture**
The only repository test for `Error400.details` still constructs and asserts the removed `{ field: "email" }` shape, so it provides no regression coverage for parsing the new `errors` array and nested `FieldError` properties. Update the fixture and assertion alongside this contract change.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Good catch — fixed in 06d7b8cb. Updated the cli/test/client.test.ts fixture and its assertion to use details: { errors: [{ field: "email" }] }, matching the new FieldError[] array contract. The test's behavior-under-test (CLI passes details through verbatim, and the whole error envelope is not nested under details) is unchanged.
Greptile SummaryUpdates the shared 400-error validation contract to return all field failures in one response.
Confidence Score: 4/5The PR appears safe to merge, with the non-blocking caveat that its Error400 parsing fixture should be updated to cover the new array response. The source schema and both generated bundles are internally consistent, but the only in-repository Error400 details test still exercises the removed singular field representation and therefore provides no regression coverage for the new nested array contract. Files Needing Attention: openapi/components/schemas/errors/Error400.yaml and cli/test/client.test.ts
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/errors/Error400.yaml | Replaces singular field-validation details with an array, but the repository's corresponding parsing fixture remains on the removed shape. |
| openapi/components/schemas/errors/FieldError.yaml | Adds a well-formed reusable field-level validation error schema with correctly resolved references. |
| openapi.yaml | Correctly contains the resolved FieldError schema and updated Error400 contract generated from the modular source. |
| mintlify/openapi.yaml | Remains synchronized with the root generated OpenAPI bundle. |
Class Diagram
%%{init: {'theme': 'neutral'}}%%
classDiagram
class Error400 {
int status
string code
string message
details
}
class ErrorDetails {
FieldError[] errors
}
class FieldError {
string field
FieldConstraint constraint
string message
}
class FieldConstraint {
string format
string pattern
string[] enum
int minLength
int maxLength
}
Error400 --> ErrorDetails
ErrorDetails --> FieldError
FieldError --> FieldConstraint
Prompt To Fix All With AI
### Issue 1
openapi/components/schemas/errors/Error400.yaml:107-113
**Obsolete Error400 test fixture**
The only repository test for `Error400.details` still constructs and asserts the removed `{ field: "email" }` shape, so it provides no regression coverage for parsing the new `errors` array and nested `FieldError` properties. Update the fixture and assertion alongside this contract change.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(errors): Error400.details.errors[] ..." | Re-trigger Greptile
Greptile flagged the fixture as stale: it constructed and asserted on
`details: { field: 'email' }` (the singular shape this PR removed).
Updated to `details: { errors: [{ field: 'email' }] }` so the test
exercises the new FieldError-array contract.
Behavior under test is unchanged (the CLI passes details through
verbatim); this just realigns the fixture with the current spec.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|

Summary
Replaces singular
details.field+details.constraintonError400with a typeddetails.errors[]array so submit endpoints (POST /customers,PATCH /customers/{id}) can report every invalid field in one round-trip.Motivation
The consumer implementation on the sparkcore side (webdev#31110) iterates all pydantic errors and emits one entry per invalid field. The spec previously only surfaced the first as machine-readable — platform integrators would have to re-submit and see the next one on each round-trip. The array shape lets them render form-field-level UX for the whole request in one shot.
Changes: 4 files
openapi/components/schemas/errors/FieldError.yaml— new schema:{field: required string, constraint?: FieldConstraint, message?: string}. One entry per invalid field.openapi/components/schemas/errors/Error400.yaml—detailsnow haserrors: arrayofFieldError; drops the singularfieldandconstraintproperties.openapi.yaml+mintlify/openapi.yaml— regenerated bundles (make build).Breaking change
details.fieldanddetails.constraintare removed at the top level ofdetails. Approved per lightsparkdev/webdev#31110 review — no external consumers had wired the previous shape into production yet, so this is safe to change in place.Skipping the
info.versionbump on that basis; happy to add one if reviewers prefer.Downstream consumer
The sparkcore side lives in lightsparkdev/webdev#31110. After this lands, that PR will regenerate the grid-api Python client and drop its backwards-compat singular field/constraint carriage on
GridException.Requested by @akanter
Original PR: #763