Skip to content

Define "execution result" and "request error result" #1159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions spec/Section 6 -- Execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,13 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):

- Let {responseStream} be a new _event stream_.
- When {sourceStream} emits {sourceValue}:
- Let {response} be the result of running
- Let {executionResult} be the result of running
{ExecuteSubscriptionEvent(subscription, schema, variableValues,
sourceValue)}.
- If internal {error} was raised:
- Cancel {sourceStream}.
- Complete {responseStream} with {error}.
- Otherwise emit {response} on {responseStream}.
- Otherwise emit {executionResult} on {responseStream}.
- When {sourceStream} completes normally:
- Complete {responseStream} normally.
- When {sourceStream} completes with {error}:
Expand Down Expand Up @@ -827,23 +827,24 @@ or coercion, at a specific _response position_. While these errors must be
reported in the response, they are "handled" by producing partial {"data"} in
the _response_.

Note: This is distinct from a _request error_ which results in a response with
no data.
Note: This is distinct from a _request error_ which results in a _request error
result_ with no data.

If an execution error is raised while resolving a field (either directly or
nested inside any lists), it is handled as though the _response position_ at
which the error occurred resolved to {null}, and the error must be added to the
{"errors"} list in the response.
{"errors"} list in the _execution result_.

If the result of resolving a _response position_ is {null} (either due to the
result of {ResolveFieldValue()} or because an execution error was raised), and
that position is of a `Non-Null` type, then an execution error is raised at that
position. The error must be added to the {"errors"} list in the response.
position. The error must be added to the {"errors"} list in the _execution
result_.

If a _response position_ resolves to {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_.
has already been added to the {"errors"} list in the _execution result_, the
{"errors"} list must not be further affected. That is, only one error should be
added to the errors list per _response position_.

Since `Non-Null` response positions cannot be {null}, execution errors are
propagated to be handled by the parent _response position_. If the parent
Expand All @@ -857,5 +858,5 @@ position_ must resolve to {null}. If the `List` type is also wrapped in a
`Non-Null`, the execution error continues to propagate upwards.

If every _response position_ from the root of the request to the source of the
execution error has a `Non-Null` type, then the {"data"} entry in the response
should be {null}.
execution error has a `Non-Null` type, then the {"data"} entry in the _execution
result_ should be {null}.
122 changes: 75 additions & 47 deletions spec/Section 7 -- Response.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,66 @@ the case that any _execution error_ was raised and replaced with {null}.

## Response Format

A GraphQL request returns either a _response_ or a _response stream_.
:: A GraphQL request returns a _response_. A _response_ is either an _execution
result_, a _response stream_, or a _request error result_.

### Response
### Execution Result

:: A GraphQL request returns a _response_ when the GraphQL operation is a query
or mutation. A _response_ must be a map.
:: A GraphQL request returns an _execution result_ when the GraphQL operation is
a query or mutation and the request included execution. Additionally, for each
event in a subscription's _source stream_, the _response stream_ will emit an
_execution result_.

If the request raised any errors, the response map must contain an entry with
key {"errors"}. The value of this entry is described in the "Errors" section. If
the request completed without raising any errors, this entry must not be
present.
An _execution result_ must be map.

If the request included execution, the response map must contain an entry with
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.
The _execution result_ must contain an entry with key {"data"}. The value of
this entry is described in the "Data" section.

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
restrictions on its contents.
If execution raised any errors, the _execution result_ must contain an entry
with key {"errors"}. The value of this entry must be a non-empty list of
_execution error_ raised during execution. Each error must be a map as described
in the "Errors" section below. If the request completed without raising any
errors, this entry must not be present.
Comment on lines +27 to +31
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved and adjusted some of the text from the Errors section. Placing it under Execution Result and Request Error Result so we can describe the specific behavior (must be included in Request Error Result, may be included in Execution Result) without the Errors section having conditions for each type.


To ensure future changes to the protocol do not break existing services and
clients, the top level response map must not contain any entries other than the
three described above.
Note: When {"errors"} is present in a _execution result_, it may be helpful for
it to appear first when serialized to make it more apparent that errors are
present.

Note: When {"errors"} is present in the response, it may be helpful for it to
appear first when serialized to make it more clear when errors are present in a
response during debugging.
The _execution result_ may also contain an entry with key `extensions`. The
value of this entry is described in the "Extensions" section.

### Response Stream

:: A GraphQL request returns a _response stream_ when the GraphQL operation is a
subscription. A _response stream_ must be a stream of _response_.
subscription and the request included execution. A response stream must be a
stream of _execution result_.

### Request Error Result

:: A GraphQL request returns a _request error result_ when one or more _request
error_ are raised, causing the request to fail before execution. This request
will result in no response data.

Note: A _request error_ may be raised before execution due to missing
information, syntax errors, validation failure, coercion failure, or any other
reason the implementation may determine should prevent the request from
proceeding.

A _request error result_ must be a map.

The _request error result_ map must contain an entry with key {"errors"}. The
value of this entry must be a non-empty list of _request error_ raised during
the _request_. It must contain at least one _request error_ indicating why no
data was able to be returned. Each error must be a map as described in the
"Errors" section below.

Note: It may be helpful for the {"errors"} key to appear first when serialized
to make it more apparent that errors are present.

The _request error result_ map must not contain an entry with key {"data"}.

The _request error result_ map may also contain an entry with key `extensions`.
The value of this entry is described in the "Extensions" section.

### Response Position

Expand Down Expand Up @@ -89,37 +115,25 @@ found at `["hero", "friends"]`, the hero's first friend at

### Data

The {"data"} entry in the response will be the result of the execution of the
requested operation. If the operation was a query, this output will be an object
of the query root operation type; if the operation was a mutation, this output
will be an object of the mutation root operation type.
The {"data"} entry in the _execution result_ will be the result of the execution
of the requested operation. If the operation was a query, this output will be an
object of the query root operation type; if the operation was a mutation, this
output will be an object of the mutation root operation type.

The response data is the result of accumulating the resolved result of all
response positions during execution.

If an error was raised before execution begins, the {"data"} entry should not be
present in the response.
If an error was raised before execution begins, the _response_ must be a
_request error result_ which will result in no response data.

If an error was raised during the execution that prevented a valid response, the
{"data"} entry in the response should be `null`.

### Errors

The {"errors"} entry in the response is a non-empty list of errors raised during
the _request_, where each error is a map of data described by the error result
format below.

If present, the {"errors"} entry in the response must contain at least one
error. If no errors were raised during the request, the {"errors"} entry must
not be present in the response.

If the {"data"} entry in the response is not present, the {"errors"} entry must
be 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
_execution error_ was raised during execution.
The {"errors"} entry in the _execution result_ or _request error result_ is a
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also define a type Response Result that includes both Execution Result and Request Error Result as subtypes, but adding another layer of hierarchy might be less clear?

non-empty list of errors raised during the _request_, where each error is a map
of data described by the error result format below.

**Request Errors**

Expand All @@ -130,9 +144,9 @@ to determine which operation to execute, or invalid input values for variables.

A request error is typically the fault of the requesting client.

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.
If a request error is raised, the _response_ must be a _request error result_.
The {"data"} entry in this map must not be present, the {"errors"} entry must
include the error, and request execution should be halted.

**Execution Errors**

Expand Down Expand Up @@ -307,6 +321,20 @@ discouraged.
}
```

### Extensions

The {"extensions"} entry in an _execution result_ or _request error result_, 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
restrictions on its contents.

### Additional Entries

To ensure future changes to the protocol do not break existing services and
clients, the _execution result_ and _request error result_ maps must not contain
any entries other than those described above. Clients must ignore any entries
other than those described above.

## Serialization Format

GraphQL does not require a specific serialization format. However, clients
Expand Down