diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md
index 945c916f6..7c84da9be 100644
--- a/spec/Section 3 -- Type System.md
+++ b/spec/Section 3 -- Type System.md
@@ -329,8 +329,8 @@ A GraphQL schema may describe that a field represents a list of another type;
the `List` type is provided for this reason, and wraps another type.
Similarly, the `Non-Null` type wraps another type, and denotes that the
-resulting value will never be {null} (and that a _field error_ cannot result in
-a {null} value).
+resulting value will never be {null} (and that an _execution error_ cannot
+result in a {null} value).
These two types are referred to as "wrapping types"; non-wrapping types are
referred to as "named types". A wrapping type has an underlying named type,
@@ -461,14 +461,14 @@ more guidance.
A GraphQL service, when preparing a field of a given scalar type, must uphold
the contract the scalar type describes, either by coercing the value or
-producing a _field error_ if a value cannot be coerced or if coercion may result
-in data loss.
+producing an _execution error_ if a value cannot be coerced or if coercion may
+result in data loss.
A GraphQL service may decide to allow coercing different internal types to the
expected return type. For example when coercing a field of type {Int} a boolean
{true} value may produce {1} or a string value {"123"} may be parsed as base-10
{123}. However if internal type coercion cannot be reasonably performed without
-losing information, then it must raise a _field error_.
+losing information, then it must raise an _execution error_.
Since this coercion behavior is not observable to clients of the GraphQL
service, the precise rules of coercion are left to the implementation. The only
@@ -513,15 +513,15 @@ Fields returning the type {Int} expect to encounter 32-bit integer internal
values.
GraphQL services may coerce non-integer internal values to integers when
-reasonable without losing information, otherwise they must raise a _field
+reasonable without losing information, otherwise they must raise an _execution
error_. Examples of this may include returning `1` for the floating-point number
`1.0`, or returning `123` for the string `"123"`. In scenarios where coercion
-may lose data, raising a field error is more appropriate. For example, a
-floating-point number `1.2` should raise a field error instead of being
+may lose data, raising an execution error is more appropriate. For example, a
+floating-point number `1.2` should raise an execution error instead of being
truncated to `1`.
If the integer internal value represents a value less than -231 or
-greater than or equal to 231, a _field error_ should be raised.
+greater than or equal to 231, an _execution error_ should be raised.
**Input Coercion**
@@ -548,12 +548,12 @@ Fields returning the type {Float} expect to encounter double-precision
floating-point internal values.
GraphQL services may coerce non-floating-point internal values to {Float} when
-reasonable without losing information, otherwise they must raise a _field
+reasonable without losing information, otherwise they must raise an _execution
error_. Examples of this may include returning `1.0` for the integer number `1`,
or `123.0` for the string `"123"`.
Non-finite floating-point internal values ({NaN} and {Infinity}) cannot be
-coerced to {Float} and must raise a _field error_.
+coerced to {Float} and must raise an _execution error_.
**Input Coercion**
@@ -579,9 +579,9 @@ that representation must be used to serialize this type.
Fields returning the type {String} expect to encounter Unicode string values.
GraphQL services may coerce non-string raw values to {String} when reasonable
-without losing information, otherwise they must raise a _field error_. Examples
-of this may include returning the string `"true"` for a boolean true value, or
-the string `"1"` for the integer `1`.
+without losing information, otherwise they must raise an _execution error_.
+Examples of this may include returning the string `"true"` for a boolean true
+value, or the string `"1"` for the integer `1`.
**Input Coercion**
@@ -600,8 +600,8 @@ representation of the integers `1` and `0`.
Fields returning the type {Boolean} expect to encounter boolean internal values.
GraphQL services may coerce non-boolean raw values to {Boolean} when reasonable
-without losing information, otherwise they must raise a _field error_. Examples
-of this may include returning `true` for non-zero numbers.
+without losing information, otherwise they must raise an _execution error_.
+Examples of this may include returning `true` for non-zero numbers.
**Input Coercion**
@@ -623,7 +623,7 @@ large 128-bit random numbers, to base64 encoded values, or string values of a
format like [GUID](https://en.wikipedia.org/wiki/Globally_unique_identifier).
GraphQL services should coerce as appropriate given the ID formats they expect.
-When coercion is not possible they must raise a _field error_.
+When coercion is not possible they must raise an _execution error_.
**Input Coercion**
@@ -1492,7 +1492,7 @@ enum Direction {
**Result Coercion**
GraphQL services must return one of the defined set of possible values. If a
-reasonable coercion is not possible they must raise a _field error_.
+reasonable coercion is not possible they must raise an _execution error_.
**Input Coercion**
@@ -1654,10 +1654,10 @@ is constructed with the following rules:
- If a variable is provided for an input object field, the runtime value of that
variable must be used. If the runtime value is {null} and the field type is
- non-null, a _field error_ must be raised. If no runtime value is provided, the
- variable definition's default value should be used. If the variable definition
- does not provide a default value, the input object field definition's default
- value should be used.
+ non-null, an _execution error_ must be raised. If no runtime value is
+ provided, the variable definition's default value should be used. If the
+ variable definition does not provide a default value, the input object field
+ definition's default value should be used.
Following are examples of input coercion for an input object type with a
`String` field `a` and a required (non-null) `Int!` field `b`:
@@ -1742,19 +1742,19 @@ brackets like this: `pets: [Pet]`. Nesting lists is allowed: `matrix: [[Int]]`.
GraphQL services must return an ordered list as the result of a list type. Each
item in the list must be the result of a result coercion of the item type. If a
-reasonable coercion is not possible it must raise a _field error_. In
+reasonable coercion is not possible it must raise an _execution error_. In
particular, if a non-list is returned, the coercion should fail, as this
indicates a mismatch in expectations between the type system and the
implementation.
If a list's item type is nullable, then errors occurring during preparation or
coercion of an individual item in the list must result in a the value {null} at
-that position in the list along with a _field error_ added to the response. If a
-list's item type is non-null, a field error occurring at an individual item in
-the list must result in a field error for the entire list.
+that position in the list along with an _execution error_ added to the response.
+If a list's item type is non-null, an execution error occurring at an individual
+item in the list must result in an execution error for the entire list.
-Note: See [Handling Field Errors](#sec-Handling-Field-Errors) for more about
-this behavior.
+Note: See [Handling Execution Errors](#sec-Handling-Execution-Errors) for more
+about this behavior.
**Input Coercion**
@@ -1812,12 +1812,13 @@ always optional and non-null types are always required.
In all of the above result coercions, {null} was considered a valid value. To
coerce the result of a Non-Null type, the coercion of the wrapped type should be
performed. If that result was not {null}, then the result of coercing the
-Non-Null type is that result. If that result was {null}, then a _field error_
-must be raised.
+Non-Null type is that result. If that result was {null}, then an _execution
+error_ must be raised.
-Note: When a _field error_ is raised on a non-null value, the error propagates
-to the parent field. For more information on this process, see
-[Errors and Non-Null Fields](#sec-Executing-Selection-Sets.Errors-and-Non-Null-Fields)
+Note: When an _execution error_ is raised on a non-null _response position_, the
+error propagates to the parent _response position_. For more information on this
+process, see
+[Errors and Non-Null Types](#sec-Executing-Selection-Sets.Errors-and-Non-Null-Types)
within the Execution section.
**Input Coercion**
diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md
index 44bc9dbba..6ca9506d2 100644
--- a/spec/Section 5 -- Validation.md
+++ b/spec/Section 5 -- Validation.md
@@ -2010,4 +2010,4 @@ query booleanArgQueryWithDefault($booleanArg: Boolean = true) {
```
Note: The value {null} could still be provided to such a variable at runtime. A
-non-null argument must raise a _field error_ if provided a {null} value.
+non-null argument must raise an _execution error_ if provided a {null} value.
diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md
index d88c685f9..72907a511 100644
--- a/spec/Section 6 -- Execution.md
+++ b/spec/Section 6 -- Execution.md
@@ -15,11 +15,26 @@ A GraphQL service generates a response from a request via execution.
being executed. Conceptually, an initial value represents the "universe" of
data available via a GraphQL Service. It is common for a GraphQL Service to
always use the same initial value for every request.
+- {onError} (optional, recommended): The _error behavior_ that is desired, see
+ [Handling Execution Errors](#sec-Handling-Execution-Errors).
Given this information, the result of {ExecuteRequest(schema, document,
operationName, variableValues, initialValue)} produces the response, to be
formatted according to the Response section below.
+Servers should use the value of {onError}, if present, as the _error behavior_
+of the request described in
+[Handling Execution Errors](#sec-Handling-Execution-Errors). However, it should
+be noted that previous versions of this specification did not make this option
+available and thus a client must not rely on the server to honor the {onError}
+value it has specified. If a _response_ includes {"errors"}, the client must
+check the {"onError"} of the _response_ determine how errors are treated. If no
+such property is present, the client must treat the request as if it had
+specified {onError} as {"PROPAGATE"}.
+
+If {onError} is present and it's value is not one of {"PROPAGATE"},
+{"NO_PROPAGATE"}, or {"ABORT"} then a request error must be raised.
+
Note: GraphQL requests do not require any specific serialization format or
transport mechanism. Message serialization and transport mechanisms should be
chosen by the implementing service.
@@ -137,7 +152,7 @@ ExecuteQuery(query, schema, variableValues, initialValue):
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
queryType, initialValue, variableValues)} _normally_ (allowing
parallelization).
-- Let {errors} be the list of all _field error_ raised while executing the
+- Let {errors} be the list of all _execution error_ raised while executing the
selection set.
- Return an unordered map containing {data} and {errors}.
@@ -158,7 +173,7 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
- Let {selectionSet} be the top level selection set in {mutation}.
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
mutationType, initialValue, variableValues)} _serially_.
-- Let {errors} be the list of all _field error_ raised while executing the
+- Let {errors} be the list of all _execution error_ raised while executing the
selection set.
- Return an unordered map containing {data} and {errors}.
@@ -317,10 +332,10 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):
- Complete {responseStream} normally.
- Return {responseStream}.
-Note: Since {ExecuteSubscriptionEvent()} handles all _field error_, and _request
-error_ only occur during {CreateSourceEventStream()}, the only remaining error
-condition handled from {ExecuteSubscriptionEvent()} are internal exceptional
-errors not described by this specification.
+Note: Since {ExecuteSubscriptionEvent()} handles all _execution error_, and
+_request error_ only occur during {CreateSourceEventStream()}, the only
+remaining error condition handled from {ExecuteSubscriptionEvent()} are internal
+exceptional errors not described by this specification.
ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
@@ -330,7 +345,7 @@ ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
subscriptionType, initialValue, variableValues)} _normally_ (allowing
parallelization).
-- Let {errors} be the list of all _field error_ raised while executing the
+- Let {errors} be the list of all _execution error_ raised while executing the
selection set.
- Return an unordered map containing {data} and {errors}.
@@ -377,17 +392,23 @@ ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues):
Note: {resultMap} is ordered by which fields appear first in the operation. This
is explained in greater detail in the Field Collection section below.
-**Errors and Non-Null Fields**
+
+
+
+
+**Errors and Non-Null Types**
-If during {ExecuteSelectionSet()} a field with a non-null {fieldType} raises a
-_field error_ then that error must propagate to this entire selection set,
-either resolving to {null} if allowed or further propagated to a parent field.
+If during {ExecuteSelectionSet()} a _response position_ with a non-null type
+raises an _execution error_ then that error must propagate to the parent
+response position (the entire selection set in the case of a field, or the
+entire list in the case of a list position), either resolving to {null} if
+allowed or being further propagated to a parent response position.
-If this occurs, any sibling fields which have not yet executed or have not yet
-yielded a value may be cancelled to avoid unnecessary work.
+If this occurs, any sibling response positions which have not yet executed or
+have not yet yielded a value may be cancelled to avoid unnecessary work.
-Note: See [Handling Field Errors](#sec-Handling-Field-Errors) for more about
-this behavior.
+Note: See [Handling Execution Errors](#sec-Handling-Execution-Errors) for more
+about this behavior.
### Normal and Serial Execution
@@ -621,6 +642,9 @@ the type system to have a specific input type.
At each argument position in an operation may be a literal {Value}, or a
{Variable} to be provided at runtime.
+Any _request error_ raised during {CoerceArgumentValues()} should be treated
+instead as an _execution error_.
+
CoerceArgumentValues(objectType, field, variableValues):
- Let {coercedValues} be an empty unordered Map.
@@ -647,7 +671,7 @@ CoerceArgumentValues(objectType, field, variableValues):
- Add an entry to {coercedValues} named {argumentName} with the value
{defaultValue}.
- Otherwise if {argumentType} is a Non-Nullable type, and either {hasValue} is
- not {true} or {value} is {null}, raise a _field error_.
+ not {true} or {value} is {null}, raise an _execution error_.
- Otherwise if {hasValue} is {true}:
- If {value} is {null}:
- Add an entry to {coercedValues} named {argumentName} with the value
@@ -657,7 +681,7 @@ CoerceArgumentValues(objectType, field, variableValues):
{value}.
- Otherwise:
- If {value} cannot be coerced according to the input coercion rules of
- {argumentType}, raise a _field error_.
+ {argumentType}, raise an _execution error_.
- Let {coercedValue} be the result of coercing {value} according to the
input coercion rules of {argumentType}.
- Add an entry to {coercedValues} named {argumentName} with the value
@@ -704,12 +728,12 @@ CompleteValue(fieldType, fields, result, variableValues):
- Let {innerType} be the inner type of {fieldType}.
- Let {completedResult} be the result of calling {CompleteValue(innerType,
fields, result, variableValues)}.
- - If {completedResult} is {null}, raise a _field error_.
+ - If {completedResult} is {null}, raise an _execution error_.
- Return {completedResult}.
- If {result} is {null} (or another internal value similar to {null} such as
{undefined}), return {null}.
- If {fieldType} is a List type:
- - If {result} is not a collection of values, raise a _field error_.
+ - If {result} is not a collection of values, raise an _execution error_.
- Let {innerType} be the inner type of {fieldType}.
- Return a list where each list item is the result of calling
{CompleteValue(innerType, fields, resultItem, variableValues)}, where
@@ -744,7 +768,7 @@ CoerceResult(leafType, value):
- Return the result of calling the internal method provided by the type system
for determining the "result coercion" of {leafType} given the value {value}.
This internal method must return a valid value for the type and not {null}.
- Otherwise raise a _field error_.
+ Otherwise raise an _execution error_.
Note: If a field resolver returns {null} then it is handled within
{CompleteValue()} before {CoerceResult()} is called. Therefore both the input
@@ -799,39 +823,89 @@ MergeSelectionSets(fields):
- Append all selections in {fieldSelectionSet} to {selectionSet}.
- Return {selectionSet}.
-### Handling Field Errors
+
+
+
+
+### Handling Execution Errors
-A _field error_ is an error raised from a particular field during value
-resolution or coercion. While these errors should be reported in the response,
-they are "handled" by producing a partial response.
+An _execution error_ is an error raised from a particular field during value
+resolution or coercion. These errors should be reported in the response and are
+"handled" according to the selected _error behavior_.
-Note: This is distinct from a _request error_ which results in a response with
-no data.
+Note: An _execution error_ is distinct from a _request error_ which results in a
+response with no data.
-If a field error is raised while resolving a field, it is handled as though the
-field returned {null}, and the error must be added to the {"errors"} list in the
-response.
+If the result of resolving a field is {null}, and that field is of a `Non-Null`
+type, then an execution error is raised by the field.
-If the result of resolving a field is {null} (either because the function to
-resolve the field returned {null} or because a field error was raised), and that
-field is of a `Non-Null` type, then a field error is raised. The error must be
-added to the {"errors"} list in the response.
+If a `List` type wraps a `Non-Null` type, and one of the elements of that list
+resolves to {null}, then an execution error is raised by the list item.
-If the field returns {null} because of a field error which has already been
-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.
+:: The _error behavior_ indicates the way in which any errors are handled during
+the request. It can be specified by the client using the {onError} property of
+the _request_. Valid values are {"PROPAGATE"}, {"NO_PROPAGATE"} and {"ABORT"};
+their respective behaviors are detailed below.
-Since `Non-Null` type fields cannot be {null}, 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.
+Implementations are free to choose the default value to use if _error behavior_
+is not specified. It is recommended this is {"NO_PROPAGATE"} for newly created
+schemas, but {"PROPAGATE"} should be used for existing schemas since that was
+the implicit behavior in previous versions of this specification.
-If a `List` type wraps a `Non-Null` type, 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
-upwards.
+Note: {"ABORT"} is not recommended as the default error behavior because it
+makes clients less resilient to errors. GraphQL enables partial responses so
+that the end user can still see some useful data even when something goes wrong
+on the server.
+
+If an execution error is raised from a response position, it must be added to
+the {"errors"} list in the _response_.
+
+If the response position returns {null} because of an execution error which has
+already been 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 _response position_.
+
+Execution errors are handled according to the selected _error behavior_, as
+detailed below:
-If all fields from the root of the request to the source of the field error
-return `Non-Null` types, then the {"data"} entry in the response should be
+**PROPAGATE**
+
+This is the traditional error handling approach in which errors are "handled" by
+producing a partial response whilst ensuring that {null} may not occur in a
+`Non-Null` position.
+
+If an execution error is raised while resolving a nullable response position, it
+is handled as though the response position returned {null} (and as stated above,
+the error must be added to the {"errors"} list in the response).
+
+Since `Non-Null` response positions cannot be {null}, execution errors that
+occur in `Non-Null` response positions are propagated to be handled by the
+parent position. If the parent response position may be {null} then it resolves
+to {null}, otherwise if it is a `Non-Null` type, the execution error is further
+propagated to its parent response position.
+
+If all response positions from the root of the request to the source of the
+execution error return `Non-Null` types, then the {"data"} entry in the response
+is made {null}.
+
+**NO_PROPAGATE**
+
+This is the modern error handling approach in which errors are "handled" by
+producing a partial response _without_ propagating errors to conform to
+`Non-Null` positions.
+
+Note: With this error behavior, the client is expected to honour the {"errors"}
+in the _response_ and prevent developers from reading a {null} produced by an
+error. One approach for clients to to prevent a {null} produced by an error from
+being read is to raise an error on the client when the data at that error's
+_path entry_ is accessed.
+
+**ABORT**
+
+This error handling approach terminates the request when an execution error is
+raised in any response position by setting the {"data"} entry in the response to
{null}.
+
+It is not recommended to default to {"ABORT"}, however it can be useful for
+certain classes of clients, such as ad-hoc scripts, that do not know how to
+handle errors and thus wish to abort and fail the moment any error occurs.
diff --git a/spec/Section 7 -- Response.md b/spec/Section 7 -- Response.md
index daca5bb1f..1579b066c 100644
--- a/spec/Section 7 -- Response.md
+++ b/spec/Section 7 -- Response.md
@@ -5,8 +5,7 @@ response. The service's response describes the result of executing the requested
operation if successful, and describes any errors raised during the request.
A response may contain both a partial response as well as a list of errors in
-the case that any _field error_ was raised on a field and was replaced with
-{null}.
+the case that any _execution error_ was raised and replaced with {null}.
## Response Format
@@ -27,6 +26,13 @@ key `data`. The value of this entry is described in the "Data" section. If the
request failed before execution, due to a syntax error, missing information, or
validation error, this entry must not be present.
+If the request included execution, raised any errors, and the _error behavior_
+was not {"PROPAGATE"} then the response map must contain an entry with key
+`onError`. Otherwise if the request included execution, the server may include
+the `onError` key. Otherwise, inclusion of the `onError` key is not recommended
+(but is permitted). The value of this key, if present, must be that of the
+_error behavior_.
+
The response map may also contain an entry with key `extensions`. This entry, if
set, must have a map as its value. This entry is reserved for implementers to
extend the protocol however they see fit, and hence there are no additional
@@ -73,8 +79,8 @@ present. It must contain at least one _request error_ indicating why no data was
able to be returned.
If the `data` entry in the response is present (including if it is the value
-{null}), the `errors` entry must be present if and only if one or more _field
-error_ was raised during execution.
+{null}), the `errors` entry must be present if and only if one or more
+_execution error_ was raised during execution.
**Request Errors**
@@ -89,18 +95,33 @@ If a request error is raised, the `data` entry in the response must not be
present, the `errors` entry must include the error, and request execution should
be halted.
-**Field Errors**
+
+
+
+
+**Execution Errors**
+
+:: An _execution error_ is an error raised during the execution of a particular
+field which results in partial response data. This may occur due to failure to
+coerce the arguments for the field, an internal error during value resolution,
+or failure to coerce the resulting value. An _execution error_ may occur in any
+_response position_.
+
+Note: In previous versions of this specification _execution error_ was called
+_field error_.
-:: A _field error_ is an error raised during the execution of a particular field
-which results in partial response data. This may occur due to an internal error
-during value resolution or failure to coerce the resulting value.
+:: A _response position_ is an identifiable position in the response: either a
+_field_, or a (potentially nested) list position within a field if the field has
+a `List` type. An _execution error_ may only occur within a _response position_.
+The _response position_ is indicated in the _response_ via the error's _path
+entry_.
-A field error is typically the fault of a GraphQL service.
+An execution error is typically the fault of a GraphQL service.
-If a field error is raised, execution attempts to continue and a partial result
-is produced (see [Handling Field Errors](#sec-Handling-Field-Errors)). The
-`data` entry in the response must be present. The `errors` entry should include
-this error.
+If an execution error is raised, execution attempts to continue and a partial
+result is produced (see
+[Handling Execution Errors](#sec-Handling-Execution-Errors)). The `data` entry
+in the response must be present. The `errors` entry must include this error.
**Error Result Format**
@@ -250,8 +271,8 @@ discouraged.
### Path
-:: A _path entry_ is an entry within an _error result_ that allows for
-association with a particular field reached during GraphQL execution.
+:: A _path entry_ is an entry within an _error result_ that indicates the
+_response position_ at which the error occurred.
The value for a _path entry_ must be a list of path segments starting at the
root of the response and ending with the field to be associated with. Path