|
| 1 | +import { Callout } from "nextra/components" |
| 2 | + |
| 3 | +# Response |
| 4 | + |
| 5 | +<p className="learn-subtitle">Learn how GraphQL returns data to clients</p> |
| 6 | + |
| 7 | +After a GraphQL document has been [validated](/learn/validation/) and [executed](/learn/execution/), the server will return a [response](https://spec.graphql.org/draft/#sec-Response) to the requesting client. One of GraphQL's strengths is that the server response reflects the shape of the client's original request, but a response may also contain helpful information if something unexpected happened before or during the execution of an operation. On this page, we'll take a deeper exploration of this final phase in the lifecycle of a GraphQL request. |
| 8 | + |
| 9 | +## Data |
| 10 | + |
| 11 | +As we have seen in the examples throughout this guide, when a GraphQL request is executed the response is returned on a top-level `data` key. For example: |
| 12 | + |
| 13 | +```graphql |
| 14 | +# { "graphiql": true } |
| 15 | +query { |
| 16 | + human(id: 1002) { |
| 17 | + name |
| 18 | + appearsIn |
| 19 | + starships { |
| 20 | + name |
| 21 | + } |
| 22 | + } |
| 23 | +} |
| 24 | +``` |
| 25 | + |
| 26 | +The inclusion of the `data` key isn't an arbitrary decision made by the underlying GraphQL implementation—it's described by the [GraphQL specification](https://spec.graphql.org/draft/#sec-Data). Under this key, you will find the result of the execution of the requested operation, which may include partial data for the requested fields if errors were raised during the execution of some field resolvers. |
| 27 | + |
| 28 | +One thing that the GraphQL specification doesn't require is a specific serialization format for the response. That said, responses are typically formatted as JSON, as in the example above. |
| 29 | + |
| 30 | +Additionally, the GraphQL specification doesn't require the use of a particular transport protocol for requests either, although it is [common for HTTP to be used](/learn/serving-over-http/) with `POST` or `GET` methods for stateless query and mutations operations. Long-lived, stateful subscription operations are often supported by WebSockets or server-sent events instead. |
| 31 | + |
| 32 | +<Callout type="info"> |
| 33 | +There is [a draft GraphQL over HTTP specification](https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md) available with further guidelines for using HTTP with a GraphQL clients and servers. |
| 34 | +</Callout> |
| 35 | + |
| 36 | +## Errors |
| 37 | + |
| 38 | +In addition to the `data` key, the GraphQL specification outlines how [errors](https://spec.graphql.org/draft/#sec-Errors) should be formatted in the response. Whether the GraphQL implementation provides partial data with the error information in the response will depend on the type of error that was raised. Let's look at the different kinds of errors that can occur during the lifecycle of a GraphQL request. |
| 39 | + |
| 40 | +### Request errors |
| 41 | + |
| 42 | +Request errors typically occur because the client made a mistake. For example, there may be a _syntax error_ in the document, such as a missing bracket or the use of an unknown root operation type keyword: |
| 43 | + |
| 44 | +```graphql |
| 45 | +# { "graphiql": true } |
| 46 | +operation { |
| 47 | + updateHumanName(id: "1000", name: "Luke Starkiller" ) { |
| 48 | + id |
| 49 | + name |
| 50 | + } |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +The `message` key inside the `errors` object provides some helpful information for the developer to understand what kind of error was raised, and the `locations` key indicates where the error occurred in the document. |
| 55 | + |
| 56 | +Sometimes, a GraphQL request may be syntactically correct, but when the server parses and [validates](/learn/validation/) the document against the schema, it finds an issue with part of the operation and raises a _validation error_. |
| 57 | + |
| 58 | +For example, the client may request a field that does not exist on the `Starship` type: |
| 59 | + |
| 60 | +```graphql |
| 61 | +# { "graphiql": true } |
| 62 | +query { |
| 63 | + starship(id: 3000) { |
| 64 | + width |
| 65 | + } |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +Validation errors also occur when clients specify incorrect variable types for their corresponding field arguments: |
| 70 | + |
| 71 | +```graphql |
| 72 | +# { "graphiql": true, "variables": { "ep": "JEDI" } } |
| 73 | +query HeroForEpisode($ep: String!) { |
| 74 | + hero(episode: $ep) { |
| 75 | + name |
| 76 | + } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +In the previous examples, we can see that when a request error occurs the `data` key will not be included because the server returns an error response to the client before the field resolvers are executed. |
| 81 | + |
| 82 | +### Field errors |
| 83 | + |
| 84 | +Field errors are raised if something unexpected happens when a resolver function is called. For example, a resolver may provide a null value for a field that has a Non-Null output type or there may be some other internal server error during execution. |
| 85 | + |
| 86 | +In these cases, the `data` key will be included in the result with the `errors` key because GraphQL will try to continue execution beyond the problematic field and potentially return a partial result. |
| 87 | + |
| 88 | +Let's look at an example: |
| 89 | + |
| 90 | +```graphql |
| 91 | +# { "graphiql": true } |
| 92 | +mutation { |
| 93 | + firstShip: deleteStarship(id: "3001") |
| 94 | + secondShip: deleteStarship(id: "3010") |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +The mutation above attempts to delete two starships in a single operation, but no starship exists with an ID of `3010` so the server throws an error. In the response, we can see information about the error that occurred for the field that was aliased as `secondShip`. Under the `data` key, we also see that the ID of the first ship was returned to indicate successful deletion, while the second ship produced a null result due to the error raised in its resolver function. |
| 99 | + |
| 100 | +### Network errors |
| 101 | + |
| 102 | +As with network calls to any type of API, network errors that are not specific to GraphQL may happen at any point during a request. These kinds of errors will block communication between the client and server before the request is complete, such as an SSL error or a connection timeout. Depending on the GraphQL server and client libraries that you choose, there may be features built into them that support special network error handling such as retries for failed operations. |
| 103 | + |
| 104 | +## Extensions |
| 105 | + |
| 106 | +The final top-level key allowed by the GraphQL specification in a response is the `extentions` key. This key is reserved for GraphQL implementations to provide additional information about the response and there are no restrictions on what it may contain. |
| 107 | + |
| 108 | +For example, some GraphQL servers may include telemetry data or information about rate limit consumption under this key. Note that what data are available in `extensions` and whether this data is available in production or development environments will depend entirely on the specific GraphQL implementation. |
| 109 | + |
| 110 | +## Next steps |
| 111 | + |
| 112 | +To recap what we've learned about GraphQL response formats: |
| 113 | + |
| 114 | +- The GraphQL specification allows three top-level keys in a response: `data`, `errors`, and `extensions` |
| 115 | +- The `data` key contains the result of the executed operation |
| 116 | +- Information about raised errors is included in the `errors` key of the response |
| 117 | +- Request errors (such as syntax or validation errors) are raised before execution begins so there won't be any data included in the response |
| 118 | +- When a field error occurs during execution, there will be a description of the issue in the `errors` key and there may be partial data included with the `data` key |
| 119 | +- GraphQL implementations may include additional arbitrary information about the response in the `extensions` key |
| 120 | + |
| 121 | +Now that you understand the different phases of a GraphQL request and how responses are provided to clients, head over to the [Introspection](/learn/introspection) page to learn about how a GraphQL server can query information about its own schema. |
0 commit comments