diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 5b7248d2b..1ed0d08cd 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -2025,7 +2025,8 @@ by a validator, executor, or client tool such as a code generator. :: A _built-in directive_ is any directive defined within this specification. -GraphQL implementations should provide the `@skip` and `@include` directives. +GraphQL implementations should provide the `@skip`, `@include` and +`@disableErrorPropagation` directives. GraphQL implementations that support the type system definition language must provide the `@deprecated` directive if representing deprecated portions of the @@ -2247,3 +2248,96 @@ to the relevant IETF specification. ```graphql example scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122") ``` + +### @disableErrorPropagation + +```graphql +directive @disableErrorPropagation on QUERY | MUTATION | SUBSCRIPTION +``` + +The `@disableErrorPropagation` _built-in directive_ may be provided on query, +mutation and subscription operations, and disables the error propagation +behavior described in [Handling Field Errors](#sec-Handling-Field-Errors) by +treating all Non-Null types as if they were instead Semantic-Non-Null types. + +Note: This is useful for clients that still wish to receive sibling fields when +an error on a Non-Null value occurs. Effectively, `@disableErrorPropagation` +enables the client to opt in to handling errors locally; for example, a client +might use this to limit the scope of null propagation to a fragment rather than +the entire field, or to update a normalized store even when an error occurs. + +Consider the following schema: + +```graphql +type Query { + me: Viewer +} + +type Viewer { + username: String! + bestFriend: Viewer! +} +``` + +If the `bestFriend` field were to return `null`, then the following operation: + +```graphql example +query myQuery { + me { + username + bestFriend { + username + } + } +} +``` + +Would return a result such as: + +```json example +{ + "errors": [ + { + "message": "Value cannot be null", + "locations": [{ "line": 4, "column": 5 }], + "path": ["me", "bestFriend"] + } + ], + "data": { + "me": null + } +} +``` + +However, if we apply the `@disableErrorPropagation` directive to our operation: + +```graphql example +query myQuery @disableErrorPropagation { + me { + username + bestFriend { + username + } + } +} +``` + +The result would contain identical errors, but the "me" field will be populated: + +```json example +{ + "errors": [ + { + "message": "Value cannot be null", + "locations": [{ "line": 4, "column": 5 }], + "path": ["me", "bestFriend"] + } + ], + "data": { + "me": { + "username": "billy", + "bestFriend": null + } + } +} +``` diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 4e7bd0571..5594b2814 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -792,14 +792,20 @@ added to the {"errors"} list in the response, the {"errors"} list must not be further affected. That is, only one error should be added to the errors list per field. -Since `Non-Null` type fields cannot be {null}, field errors are propagated to be +If the operation provides the `@disableErrorPropagation` directive then +`Non-Null` type fields will become {null} if an error occurs. + +If the operation does not provide the `@disableErrorPropagation` directive then +`Non-Null` type fields cannot be {null}, and field errors are propagated to be handled by the parent field. If the parent field may be {null} then it resolves to {null}, otherwise if it is a `Non-Null` type, the field error is further propagated to its parent field. -If a `List` type wraps a `Non-Null` type, and one of the elements of that list +If a `List` type wraps a `Non-Null` type, the operation does not provide the +`@disableErrorPropagation` directive, and one of the elements of that list resolves to {null}, then the entire list must resolve to {null}. If the `List` -type is also wrapped in a `Non-Null`, the field error continues to propagate +type is also wrapped in a `Non-Null` and the operation does not provide the +`@disableErrorPropagation` directive, the field error continues to propagate upwards. If all fields from the root of the request to the source of the field error