At a glance
- Identifier: #1163
- Stage: RFC 1 / Proposal
- Champion: @benjie
- Latest activity: Added to WG agenda on 2026-01-15
- Spec PR: https://github.com/graphql/graphql-spec/pull/1163
- Related:
Spec PR description
This is a rewrite of
- #1153
It is re-implemented on top of the recent editorial work (e.g. renaming _field error_ to _execution error_) and also makes a significant change in that it does not require onError to be included in the response, instead an introspection field is used to indicate:
- that
onErroris supported - what the behavior will be if
onErroris not present
Replaces:
- #1050
- #1145
- #1153
GraphQL.js implementation:
Please see this 60 second video on the motivation for this PR (the last few seconds of the video also covers "transitional non-null" which is a separate concern).
As agreed at the nullability working group, disabling error propagation is the future of error handling in GraphQL. Error propagation causes a number of issues, but chief among them are:
- It destroys useful data in the response.
- It makes it unsafe to store resulting data in normalized stores.
Clients such as Relay do not want error propagation to be a thing.
This has traditionally resulted in schema design best practices advising using nullable in positions where errors were expected, even if null was never a semantically valid value for that position. And since errors can happen everywhere, this has lead to an explosion of nullability and significant pain on the client side with developers having to do seemingly unnecessary null checks in loads of positions, or worse - unsafely bypassing the type safety.
The reason that GraphQL does error propagation is to keep it's "not null" promise in the event that an error occurs (and is replaced with null due to the way GraphQL responses are structured and limitations in JSON) in a non-nullable position.
It doesn't take much code on the client to prevent the client reading a null that relates to an error, graphql-toe can be used with almost any JavaScript or TypeScript based GraphQL client (not Relay, but it has @throwOnFieldError that you can use instead) and achieves this in 512 bytes gzipped - and that's with a focus on performance rather than bundle size.
This PR allows the client to take responsibility for error handling by specifying onError: "NULL" as part of the GraphQL request, and thereby turns off error propagation behavior. This is also set as the recommended default for future schemas.
With clients responsible for error handling, we no longer need to factor the possibility of whether something can error or not into its nullability, meaning we can use the not-null ! to indicate all the positions in the schema for which null is not a semantically valid value - i.e. the underlying resource will never be a legitimate null.
The end result:
- true nullability indicated in schema - no more thinking about where errors are likely
- fewer null checks on clients
- clients can leverage their native error handling capabilities such as try/catch or
<ErrorBoundary /> - safe to store errored responses into normalized stores
I've also included onError: "HALT" in this proposal. We've discovered that there's a small but significant class of clients out there, mostly ad-hoc scripts, that throw away the entire response when any error occurs. By codifying this into the spec we make it easier to implement these clients, and we allow the server to halt processing the rest of the request unnecessarily.
As noted by @revangen in this comment:
I've also included onError:
"ABORT""HALT" in this proposal.Appreciate this being included. For Shopify's public Admin GraphQL API, we have a mix of scenarios that result in a partial success response and only error response. Having been around for 8+ years, we are reluctant at times to change its behaviour to favour partial responses as we don't control majority of clients. Providing clients a way to specify the server's behaviour provides a migration path should clients care about partial responses.
Timeline
- Added to WG agenda on 2026-01-15
- Mentioned in WG notes on 2026-01-01
- 4 commits pushed on 2025-11-06:
- benjie committed "Remove unnecessary negative lookahead"
- benjie committed "Lee says empty braces are okay here!"
- benjie committed "Merge branch 'main' into error-behavior2"
- benjie committed "Sync syntax with Lee's suggestions"
- Added to WG agenda on 2025-11-06
- Commit pushed on 2025-10-28 by benjie: Fix incorrect prefix
- 9 commits pushed on 2025-08-29:
- benjie committed "Overhaul and introduce SDL syntax for service capabilities"
- benjie committed "Update syntax"
- benjie committed "Simplify"
- benjie committed "Update Name syntax"
- benjie committed "Clarification"
- benjie committed "Minor tweaks"
- benjie committed "Clarify the interaction of onError:HALT and subscriptions"
- benjie committed "Fix grammar"
- benjie committed "Spelling"
- 2 commits pushed on 2025-07-10:
- benjie committed "Merge branch 'main' into error-behavior2"
- benjie committed "Change NO_PROPAGATE to NULL"
- Added to WG agenda on 2025-06-05
- Commit pushed on 2025-05-28 by benjie: Update spec/Section 4 -- Introspection.md
- 7 commits pushed on 2025-05-22:
- benjie committed "Rework capabilities"
- benjie committed "Use a definition"
- benjie committed "Reorder"
- benjie committed "Reword"
- benjie committed "Editorial"
- benjie committed "More editorial"
- benjie committed "More editorial"
- 4 commits pushed on 2025-05-15:
- benjie committed "ABORT -> HALT"
- benjie committed "Start speccing out the capabilities system"
- benjie committed "Add a number of basic capabilities"
- benjie committed "Move default error behavior to the service"
- Added to WG agenda on 2025-05-15
- Added to WG agenda on 2025-05-01
- Spec PR created on 2025-04-30 by benjie
- 3 commits pushed on 2025-04-30:
- benjie committed "Detail onError request parameter"
- benjie committed "Detail introspection changes"
- benjie committed "Define the directive"