Skip to content

Commit 521ef5b

Browse files
benjieleebyron
andauthored
Rename field error to execution error; define response position (#1152)
* Rename 'field error' to 'runtime error' and define 'error position' * Request errors should not be raised during CoerceArgumentValues * Typo * Rename 'runtime error' to 'execution error' * Oops, missed out these edits * Use definition in final paragraph * lift up + other feedback * lift response position to top section --------- Co-authored-by: Lee Byron <[email protected]>
1 parent 4abd86e commit 521ef5b

4 files changed

+200
-139
lines changed

Diff for: spec/Section 3 -- Type System.md

+34-33
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ A GraphQL schema may describe that a field represents a list of another type;
329329
the `List` type is provided for this reason, and wraps another type.
330330

331331
Similarly, the `Non-Null` type wraps another type, and denotes that the
332-
resulting value will never be {null} (and that a _field error_ cannot result in
333-
a {null} value).
332+
resulting value will never be {null} (and that an _execution error_ cannot
333+
result in a {null} value).
334334

335335
These two types are referred to as "wrapping types"; non-wrapping types are
336336
referred to as "named types". A wrapping type has an underlying named type,
@@ -461,14 +461,14 @@ more guidance.
461461

462462
A GraphQL service, when preparing a field of a given scalar type, must uphold
463463
the contract the scalar type describes, either by coercing the value or
464-
producing a _field error_ if a value cannot be coerced or if coercion may result
465-
in data loss.
464+
producing an _execution error_ if a value cannot be coerced or if coercion may
465+
result in data loss.
466466

467467
A GraphQL service may decide to allow coercing different internal types to the
468468
expected return type. For example when coercing a field of type {Int} a boolean
469469
{true} value may produce {1} or a string value {"123"} may be parsed as base-10
470470
{123}. However if internal type coercion cannot be reasonably performed without
471-
losing information, then it must raise a _field error_.
471+
losing information, then it must raise an _execution error_.
472472

473473
Since this coercion behavior is not observable to clients of the GraphQL
474474
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
513513
values.
514514

515515
GraphQL services may coerce non-integer internal values to integers when
516-
reasonable without losing information, otherwise they must raise a _field
516+
reasonable without losing information, otherwise they must raise an _execution
517517
error_. Examples of this may include returning `1` for the floating-point number
518518
`1.0`, or returning `123` for the string `"123"`. In scenarios where coercion
519-
may lose data, raising a field error is more appropriate. For example, a
520-
floating-point number `1.2` should raise a field error instead of being
519+
may lose data, raising an execution error is more appropriate. For example, a
520+
floating-point number `1.2` should raise an execution error instead of being
521521
truncated to `1`.
522522

523523
If the integer internal value represents a value less than -2<sup>31</sup> or
524-
greater than or equal to 2<sup>31</sup>, a _field error_ should be raised.
524+
greater than or equal to 2<sup>31</sup>, an _execution error_ should be raised.
525525

526526
**Input Coercion**
527527

@@ -548,12 +548,12 @@ Fields returning the type {Float} expect to encounter double-precision
548548
floating-point internal values.
549549

550550
GraphQL services may coerce non-floating-point internal values to {Float} when
551-
reasonable without losing information, otherwise they must raise a _field
551+
reasonable without losing information, otherwise they must raise an _execution
552552
error_. Examples of this may include returning `1.0` for the integer number `1`,
553553
or `123.0` for the string `"123"`.
554554

555555
Non-finite floating-point internal values ({NaN} and {Infinity}) cannot be
556-
coerced to {Float} and must raise a _field error_.
556+
coerced to {Float} and must raise an _execution error_.
557557

558558
**Input Coercion**
559559

@@ -579,9 +579,9 @@ that representation must be used to serialize this type.
579579
Fields returning the type {String} expect to encounter Unicode string values.
580580

581581
GraphQL services may coerce non-string raw values to {String} when reasonable
582-
without losing information, otherwise they must raise a _field error_. Examples
583-
of this may include returning the string `"true"` for a boolean true value, or
584-
the string `"1"` for the integer `1`.
582+
without losing information, otherwise they must raise an _execution error_.
583+
Examples of this may include returning the string `"true"` for a boolean true
584+
value, or the string `"1"` for the integer `1`.
585585

586586
**Input Coercion**
587587

@@ -600,8 +600,8 @@ representation of the integers `1` and `0`.
600600
Fields returning the type {Boolean} expect to encounter boolean internal values.
601601

602602
GraphQL services may coerce non-boolean raw values to {Boolean} when reasonable
603-
without losing information, otherwise they must raise a _field error_. Examples
604-
of this may include returning `true` for non-zero numbers.
603+
without losing information, otherwise they must raise an _execution error_.
604+
Examples of this may include returning `true` for non-zero numbers.
605605

606606
**Input Coercion**
607607

@@ -623,7 +623,7 @@ large 128-bit random numbers, to base64 encoded values, or string values of a
623623
format like [GUID](https://en.wikipedia.org/wiki/Globally_unique_identifier).
624624

625625
GraphQL services should coerce as appropriate given the ID formats they expect.
626-
When coercion is not possible they must raise a _field error_.
626+
When coercion is not possible they must raise an _execution error_.
627627

628628
**Input Coercion**
629629

@@ -1492,7 +1492,7 @@ enum Direction {
14921492
**Result Coercion**
14931493

14941494
GraphQL services must return one of the defined set of possible values. If a
1495-
reasonable coercion is not possible they must raise a _field error_.
1495+
reasonable coercion is not possible they must raise an _execution error_.
14961496

14971497
**Input Coercion**
14981498

@@ -1654,10 +1654,10 @@ is constructed with the following rules:
16541654

16551655
- If a variable is provided for an input object field, the runtime value of that
16561656
variable must be used. If the runtime value is {null} and the field type is
1657-
non-null, a _field error_ must be raised. If no runtime value is provided, the
1658-
variable definition's default value should be used. If the variable definition
1659-
does not provide a default value, the input object field definition's default
1660-
value should be used.
1657+
non-null, an _execution error_ must be raised. If no runtime value is
1658+
provided, the variable definition's default value should be used. If the
1659+
variable definition does not provide a default value, the input object field
1660+
definition's default value should be used.
16611661

16621662
Following are examples of input coercion for an input object type with a
16631663
`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]]`.
17421742

17431743
GraphQL services must return an ordered list as the result of a list type. Each
17441744
item in the list must be the result of a result coercion of the item type. If a
1745-
reasonable coercion is not possible it must raise a _field error_. In
1745+
reasonable coercion is not possible it must raise an _execution error_. In
17461746
particular, if a non-list is returned, the coercion should fail, as this
17471747
indicates a mismatch in expectations between the type system and the
17481748
implementation.
17491749

17501750
If a list's item type is nullable, then errors occurring during preparation or
17511751
coercion of an individual item in the list must result in a the value {null} at
1752-
that position in the list along with a _field error_ added to the response. If a
1753-
list's item type is non-null, a field error occurring at an individual item in
1754-
the list must result in a field error for the entire list.
1752+
that position in the list along with an _execution error_ added to the response.
1753+
If a list's item type is non-null, an execution error occurring at an individual
1754+
item in the list must result in an execution error for the entire list.
17551755

1756-
Note: See [Handling Field Errors](#sec-Handling-Field-Errors) for more about
1757-
this behavior.
1756+
Note: See [Handling Execution Errors](#sec-Handling-Execution-Errors) for more
1757+
about this behavior.
17581758

17591759
**Input Coercion**
17601760

@@ -1812,12 +1812,13 @@ always optional and non-null types are always required.
18121812
In all of the above result coercions, {null} was considered a valid value. To
18131813
coerce the result of a Non-Null type, the coercion of the wrapped type should be
18141814
performed. If that result was not {null}, then the result of coercing the
1815-
Non-Null type is that result. If that result was {null}, then a _field error_
1816-
must be raised.
1815+
Non-Null type is that result. If that result was {null}, then an _execution
1816+
error_ must be raised.
18171817

1818-
Note: When a _field error_ is raised on a non-null value, the error propagates
1819-
to the parent field. For more information on this process, see
1820-
[Errors and Non-Null Fields](#sec-Executing-Selection-Sets.Errors-and-Non-Null-Fields)
1818+
Note: When an _execution error_ is raised on a non-null _response position_, the
1819+
error propagates to the parent _response position_. For more information on this
1820+
process, see
1821+
[Errors and Non-Null Types](#sec-Executing-Selection-Sets.Errors-and-Non-Null-Types)
18211822
within the Execution section.
18221823

18231824
**Input Coercion**

Diff for: spec/Section 5 -- Validation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2010,4 +2010,4 @@ query booleanArgQueryWithDefault($booleanArg: Boolean = true) {
20102010
```
20112011

20122012
Note: The value {null} could still be provided to such a variable at runtime. A
2013-
non-null argument must raise a _field error_ if provided a {null} value.
2013+
non-null argument must raise an _execution error_ if provided a {null} value.

Diff for: spec/Section 6 -- Execution.md

+67-51
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ ExecuteQuery(query, schema, variableValues, initialValue):
137137
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
138138
queryType, initialValue, variableValues)} _normally_ (allowing
139139
parallelization).
140-
- Let {errors} be the list of all _field error_ raised while executing the
140+
- Let {errors} be the list of all _execution error_ raised while executing the
141141
selection set.
142142
- Return an unordered map containing {data} and {errors}.
143143

@@ -158,7 +158,7 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
158158
- Let {selectionSet} be the top level selection set in {mutation}.
159159
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
160160
mutationType, initialValue, variableValues)} _serially_.
161-
- Let {errors} be the list of all _field error_ raised while executing the
161+
- Let {errors} be the list of all _execution error_ raised while executing the
162162
selection set.
163163
- Return an unordered map containing {data} and {errors}.
164164

@@ -317,10 +317,10 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):
317317
- Complete {responseStream} normally.
318318
- Return {responseStream}.
319319

320-
Note: Since {ExecuteSubscriptionEvent()} handles all _field error_, and _request
321-
error_ only occur during {CreateSourceEventStream()}, the only remaining error
322-
condition handled from {ExecuteSubscriptionEvent()} are internal exceptional
323-
errors not described by this specification.
320+
Note: Since {ExecuteSubscriptionEvent()} handles all _execution error_, and
321+
_request error_ only occur during {CreateSourceEventStream()}, the only
322+
remaining error condition handled from {ExecuteSubscriptionEvent()} are internal
323+
exceptional errors not described by this specification.
324324

325325
ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
326326

@@ -330,7 +330,7 @@ ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
330330
- Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
331331
subscriptionType, initialValue, variableValues)} _normally_ (allowing
332332
parallelization).
333-
- Let {errors} be the list of all _field error_ raised while executing the
333+
- Let {errors} be the list of all _execution error_ raised while executing the
334334
selection set.
335335
- Return an unordered map containing {data} and {errors}.
336336

@@ -376,17 +376,23 @@ ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues):
376376
Note: {resultMap} is ordered by which fields appear first in the operation. This
377377
is explained in greater detail in the Field Collection section below.
378378

379-
**Errors and Non-Null Fields**
379+
**Errors and Non-Null Types**
380380

381-
If during {ExecuteSelectionSet()} a field with a non-null {fieldType} raises a
382-
_field error_ then that error must propagate to this entire selection set,
383-
either resolving to {null} if allowed or further propagated to a parent field.
381+
<a name="sec-Executing-Selection-Sets.Errors-and-Non-Null-Fields">
382+
<!-- Legacy link, this section was previously titled "Errors and Non-Null Fields" -->
383+
</a>
384384

385-
If this occurs, any sibling fields which have not yet executed or have not yet
386-
yielded a value may be cancelled to avoid unnecessary work.
385+
If during {ExecuteSelectionSet()} a _response position_ with a non-null type
386+
raises an _execution error_ then that error must propagate to the parent
387+
response position (the entire selection set in the case of a field, or the
388+
entire list in the case of a list position), either resolving to {null} if
389+
allowed or being further propagated to a parent response position.
387390

388-
Note: See [Handling Field Errors](#sec-Handling-Field-Errors) for more about
389-
this behavior.
391+
If this occurs, any sibling response positions which have not yet executed or
392+
have not yet yielded a value may be cancelled to avoid unnecessary work.
393+
394+
Note: See [Handling Execution Errors](#sec-Handling-Execution-Errors) for more
395+
about this behavior.
390396

391397
### Normal and Serial Execution
392398

@@ -646,7 +652,7 @@ CoerceArgumentValues(objectType, field, variableValues):
646652
- Add an entry to {coercedValues} named {argumentName} with the value
647653
{defaultValue}.
648654
- Otherwise if {argumentType} is a Non-Nullable type, and either {hasValue} is
649-
not {true} or {value} is {null}, raise a _field error_.
655+
not {true} or {value} is {null}, raise an _execution error_.
650656
- Otherwise if {hasValue} is {true}:
651657
- If {value} is {null}:
652658
- Add an entry to {coercedValues} named {argumentName} with the value
@@ -656,13 +662,16 @@ CoerceArgumentValues(objectType, field, variableValues):
656662
{value}.
657663
- Otherwise:
658664
- If {value} cannot be coerced according to the input coercion rules of
659-
{argumentType}, raise a _field error_.
665+
{argumentType}, raise an _execution error_.
660666
- Let {coercedValue} be the result of coercing {value} according to the
661667
input coercion rules of {argumentType}.
662668
- Add an entry to {coercedValues} named {argumentName} with the value
663669
{coercedValue}.
664670
- Return {coercedValues}.
665671

672+
Any _request error_ raised as a result of input coercion during
673+
{CoerceArgumentValues()} should be treated instead as an _execution error_.
674+
666675
Note: Variable values are not coerced because they are expected to be coerced
667676
before executing the operation in {CoerceVariableValues()}, and valid operations
668677
must only allow usage of variables of appropriate types.
@@ -703,12 +712,12 @@ CompleteValue(fieldType, fields, result, variableValues):
703712
- Let {innerType} be the inner type of {fieldType}.
704713
- Let {completedResult} be the result of calling {CompleteValue(innerType,
705714
fields, result, variableValues)}.
706-
- If {completedResult} is {null}, raise a _field error_.
715+
- If {completedResult} is {null}, raise an _execution error_.
707716
- Return {completedResult}.
708717
- If {result} is {null} (or another internal value similar to {null} such as
709718
{undefined}), return {null}.
710719
- If {fieldType} is a List type:
711-
- If {result} is not a collection of values, raise a _field error_.
720+
- If {result} is not a collection of values, raise an _execution error_.
712721
- Let {innerType} be the inner type of {fieldType}.
713722
- Return a list where each list item is the result of calling
714723
{CompleteValue(innerType, fields, resultItem, variableValues)}, where
@@ -743,7 +752,7 @@ CoerceResult(leafType, value):
743752
- Return the result of calling the internal method provided by the type system
744753
for determining the "result coercion" of {leafType} given the value {value}.
745754
This internal method must return a valid value for the type and not {null}.
746-
Otherwise raise a _field error_.
755+
Otherwise raise an _execution error_.
747756

748757
Note: If a field resolver returns {null} then it is handled within
749758
{CompleteValue()} before {CoerceResult()} is called. Therefore both the input
@@ -798,39 +807,46 @@ MergeSelectionSets(fields):
798807
- Append all selections in {fieldSelectionSet} to {selectionSet}.
799808
- Return {selectionSet}.
800809

801-
### Handling Field Errors
810+
### Handling Execution Errors
811+
812+
<a name="sec-Handling-Field-Errors">
813+
<!-- Legacy link, this section was previously titled "Handling Execution Errors" -->
814+
</a>
802815

803-
A _field error_ is an error raised from a particular field during value
804-
resolution or coercion. While these errors should be reported in the response,
805-
they are "handled" by producing a partial response.
816+
An _execution error_ is an error raised during field execution, value resolution
817+
or coercion, at a specific _response position_. While these errors must be
818+
reported in the response, they are "handled" by producing partial {"data"} in
819+
the _response_.
806820

807821
Note: This is distinct from a _request error_ which results in a response with
808822
no data.
809823

810-
If a field error is raised while resolving a field, it is handled as though the
811-
field returned {null}, and the error must be added to the {"errors"} list in the
812-
response.
813-
814-
If the result of resolving a field is {null} (either because the function to
815-
resolve the field returned {null} or because a field error was raised), and that
816-
field is of a `Non-Null` type, then a field error is raised. The error must be
817-
added to the {"errors"} list in the response.
818-
819-
If the field returns {null} because of a field error which has already been
820-
added to the {"errors"} list in the response, the {"errors"} list must not be
821-
further affected. That is, only one error should be added to the errors list per
822-
field.
823-
824-
Since `Non-Null` type fields cannot be {null}, field errors are propagated to be
825-
handled by the parent field. If the parent field may be {null} then it resolves
826-
to {null}, otherwise if it is a `Non-Null` type, the field error is further
827-
propagated to its parent field.
828-
829-
If a `List` type wraps a `Non-Null` type, and one of the elements of that list
830-
resolves to {null}, then the entire list must resolve to {null}. If the `List`
831-
type is also wrapped in a `Non-Null`, the field error continues to propagate
832-
upwards.
833-
834-
If all fields from the root of the request to the source of the field error
835-
return `Non-Null` types, then the {"data"} entry in the response should be
836-
{null}.
824+
If an execution error is raised while resolving a field (either directly or
825+
nested inside any lists), it is handled as though the _response position_ at
826+
which the error occurred resolved to {null}, and the error must be added to the
827+
{"errors"} list in the response.
828+
829+
If the result of resolving a _response position_ is {null} (either due to the
830+
result of {ResolveFieldValue()} or because an execution error was raised), and
831+
that position is of a `Non-Null` type, then an execution error is raised at that
832+
position. The error must be added to the {"errors"} list in the response.
833+
834+
If a _response position_ resolves to {null} because of an execution error which
835+
has already been added to the {"errors"} list in the response, the {"errors"}
836+
list must not be further affected. That is, only one error should be added to
837+
the errors list per _response position_.
838+
839+
Since `Non-Null` response positions cannot be {null}, execution errors are
840+
propagated to be handled by the parent _response position_. If the parent
841+
response position may be {null} then it resolves to {null}, otherwise if it is a
842+
`Non-Null` type, the execution error is further propagated to its parent
843+
_response position_.
844+
845+
If a `List` type wraps a `Non-Null` type, and one of the _response position_
846+
elements of that list resolves to {null}, then the entire list _response
847+
position_ must resolve to {null}. If the `List` type is also wrapped in a
848+
`Non-Null`, the execution error continues to propagate upwards.
849+
850+
If every _response position_ from the root of the request to the source of the
851+
execution error has a `Non-Null` type, then the {"data"} entry in the response
852+
should be {null}.

0 commit comments

Comments
 (0)