Proposal: Omit fields when their resolver fails (optional execution mode, no new syntax) #1871
Closed
nikolayandr
started this conversation in
Ideas
Replies: 1 comment 1 reply
-
|
Hi @nikolayandr; have you seen the new "error behaviors" proposal to come out of the nullability working group? You can read the spec changes here: graphql/graphql-spec#1163 and I did a talk about it at GraphQL Conf: https://graphql.org/conf/2025/schedule/4ed67778faddda05ce0a191e525d43ee/ I also have a 60 second video as an incredibly short intro here: https://www.youtube.com/shorts/meE3HRkgK-E Also check out related projects such as https://github.com/graphile/graphql-toe and https://github.com/graphile/graphql-sock After checking these out, please indicate if you'd still like to push your proposal forward. We'd be happy to discuss it! |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Hi all,
I would like to propose an execution-level idea intended to address ambiguity around null values produced by resolver errors in GraphQL responses. This proposal does not introduce any new syntax or type modifiers; it is an optional execution mode that keeps GraphQL fully backwards-compatible.
This discussion is intentionally lightweight — the goal is to validate the idea and get initial feedback before considering a formal RFC.
💡 Proposal (optional execution mode)
If a resolver fails, omit the field entirely from the data response.
The failure is reported only in errors[], not as a null value.
This applies to:
Null bubbling is skipped in this opt-in mode.
🎯 Problem
When a resolver fails today, GraphQL behaves in one of two ways depending on the field’s nullability:
{ "field": null }and an entry in errors[].
Example:
If the price resolver fails, the response must be:
{ "data": { "product": null }, "errors": [ { "message": "timeout", "path": ["product","price"] } ] }This behavior is mandatory in the current GraphQL specification.
Servers cannot avoid bubbling while remaining spec-compliant.
The core issue
A client receiving:
cannot distinguish, from the data section alone, whether:
Yes, clients can inspect the errors[] array, but in practice it adds complexity
This is the ambiguity the proposal aims to address.
💡 Proposed: optional “omit-on-error” execution mode
If a resolver fails, omit the field entirely from data.
The failure is reported only in errors[], not by returning null.
Key points:
This mode introduces a clearer separation between:
📘 Examples
Today:
{ "data": { "product": { "sku": "SKU1", "price": null } }, "errors": [ { "message": "timeout", "path": ["product","price"] } ] }Proposed:
{ "data": { "product": {"sku": "SKU1"} }, "errors": [ { "message": "timeout", "path": ["product","price"] } ] }Today — required null bubbling:
{ "data": { "product": null }, "errors": [ { "message": "timeout", "path": ["product","price"] } ] }Proposed (in the optional execution mode):
{ "data": { "product": { "sku": "SKU1" } }, "errors": [ { "message": "timeout", "path": ["product","price"] } ] }The parent object remains intact.
The problematic field is simply omitted.
Return an empty object {} at that index (to preserve list shape) and report the error:
{ "data": { "products": [ { sku: "SKU1", "price": 1.0 }, {} ] }, "errors": [ { "message": "failed", "path": ["products",1] } ] }If only a nested field fails, only that field is omitted:
{ "data": { "products": [ { sku: "SKU1", "price": 1.0 }, { sku: "SKU2"} ] }, "errors": [ { "message": "failed", "path": ["products",1, "price"] } ] }🟩 Benefits
Beta Was this translation helpful? Give feedback.
All reactions