diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index beee413ae..32e85b9ea 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -2018,7 +2018,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 +`@nullOnError` directives. GraphQL implementations that support the type system definition language must provide the `@deprecated` directive if representing deprecated portions of the @@ -2240,3 +2241,96 @@ to the relevant IETF specification. ```graphql example scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122") ``` + +### @nullOnError + +```graphql +directive @nullOnError on QUERY | MUTATION | SUBSCRIPTION +``` + +The `@nullOnError` _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 Null-Only-On-Error types. + +Note: This is useful for clients that still wish to receive sibling fields when +an error on a Non-Null value occurs. Effectively, `@nullOnError` 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 `@nullOnError` directive to our operation: + +```graphql example +query myQuery @nullOnError { + 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 + } + } +} +```