You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
contains a number of queries demonstrating various invalidities, and is a test
11
-
file that can be run to exercise the reference implementation's validator.
5
+
On this page, we'll explore an important phase in the lifecycle of a GraphQL request called [validation](https://spec.graphql.org/draft/#sec-Validation). A request must be syntactically correct to run, but it should also be valid when checked against the API's schema.
12
6
13
-
To start, let's take a complex valid query. This is a nested query, similar to
14
-
an example from the previous section, but with the duplicated fields factored
15
-
out into a fragment:
7
+
In practice, when a GraphQL operation reaches the server, the document is first parsed and then validated using the type system. This allows servers and clients to effectively inform developers when an invalid query has been created, and without relying on runtime checks. Once the operation is validated, it can be [executed](/learn/execution/) on the server and a response will be delivered to the client.
16
8
17
-
```graphql
18
-
# { "graphiql": true }
19
-
{
20
-
hero {
21
-
...NameAndAppearances
22
-
friends {
23
-
...NameAndAppearances
24
-
friends {
25
-
...NameAndAppearances
26
-
}
27
-
}
28
-
}
29
-
}
30
-
31
-
fragmentNameAndAppearancesonCharacter {
32
-
name
33
-
appearsIn
34
-
}
35
-
```
36
-
37
-
And this query is valid. Let's take a look at some invalid queries...
38
-
39
-
A fragment cannot refer to itself or create a cycle, as this could result in
40
-
an unbounded result! Here's the same query above but without the explicit three
41
-
levels of nesting:
9
+
## Validation examples
42
10
43
-
```graphql
44
-
# { "graphiql": true }
45
-
{
46
-
hero {
47
-
...NameAndAppearancesAndFriends
48
-
}
49
-
}
11
+
The GraphQL specification describes the detailed conditions that must be satisfied for a request to be considered valid. In the sections that follow, we'll look at a few examples of common validation issues that occur in GraphQL operations.
50
12
51
-
fragmentNameAndAppearancesAndFriendsonCharacter {
52
-
name
53
-
appearsIn
54
-
friends {
55
-
...NameAndAppearancesAndFriends
56
-
}
57
-
}
58
-
```
13
+
### Requesting non-existent fields
59
14
60
-
When we query for fields, we have to query for a field that exists on the
61
-
given type. So as `hero` returns a `Character`, we have to query for a field
62
-
on `Character`. That type does not have a `favoriteSpaceship` field, so this
63
-
query is invalid:
15
+
When we query for fields, we have to request a field on the given type. So as `hero` returns a `Character` type, we have to query for a field that's defined on `Character`. That type does not have a `favoriteSpaceship` field, so this query is invalid:
64
16
65
17
```graphql
66
18
# { "graphiql": true }
67
19
# INVALID: favoriteSpaceship does not exist on Character
68
-
{
20
+
query{
69
21
hero {
70
22
favoriteSpaceship
71
23
}
72
24
}
73
25
```
74
26
75
-
Whenever we query for a field and it returns something other than a scalar
76
-
or an enum, we need to specify what data we want to get back from the field.
77
-
Hero returns a `Character`, and we've been requesting fields like `name` and
78
-
`appearsIn` on it; if we omit that, the query will not be valid:
27
+
### Selecting invalid leaf fields
28
+
29
+
Whenever we query for a field and it returns something other than a Scalar or Enum type, we need to specify what data we want to get back from the field. The `hero` query field returns a `Character`, and we've already seen examples that request fields like `name` and `appearsIn` on it. If we omit those leaf field selections, then the query will not be valid:
79
30
80
31
```graphql
81
32
# { "graphiql": true }
82
33
# INVALID: hero is not a scalar, so fields are needed
83
-
{
34
+
query{
84
35
hero
85
36
}
86
37
```
87
38
88
-
Similarly, if a field is a scalar, it doesn't make sense to query for
89
-
additional fields on it, and doing so will make the query invalid:
39
+
Similarly, if the leaf field is a scalar value, it doesn't make sense to query for additional fields on it, and doing so will make the query invalid:
90
40
91
41
```graphql
92
42
# { "graphiql": true }
93
43
# INVALID: name is a scalar, so fields are not permitted
94
-
{
44
+
query{
95
45
hero {
96
46
name {
97
47
firstCharacterOfName
@@ -100,32 +50,26 @@ additional fields on it, and doing so will make the query invalid:
100
50
}
101
51
```
102
52
103
-
Earlier, it was noted that a query can only query for fields on the type
104
-
in question; when we query for `hero` which returns a `Character`, we
105
-
can only query for fields that exist on `Character`. What happens if we
106
-
want to query for R2-D2s primary function, though?
53
+
### Missing fragments for fields that output abstract types
54
+
55
+
Earlier, it was noted that a query can only ask for fields on the type in question. So when we query for `hero` which returns a `Character`, we can only request fields that exist on the `Character` Interface type. What happens if we want to query for R2-D2's primary function, though?
107
56
108
57
```graphql
109
58
# { "graphiql": true }
110
59
# INVALID: primaryFunction does not exist on Character
111
-
{
60
+
query{
112
61
hero {
113
62
name
114
63
primaryFunction
115
64
}
116
65
}
117
66
```
118
67
119
-
That query is invalid, because `primaryFunction` is not a field on `Character`.
120
-
We want some way of indicating that we wish to fetch `primaryFunction` if the
121
-
`Character` is a `Droid`, and to ignore that field otherwise. We can use
122
-
the fragments we introduced earlier to do this. By setting up a fragment defined
123
-
on `Droid` and including it, we ensure that we only query for `primaryFunction`
124
-
where it is defined.
68
+
That query is invalid, because `primaryFunction` is not one of the shared fields defined by the `Character` Interface type. We want some way of indicating that we wish to fetch `primaryFunction` if the `Character` is a `Droid`, and to ignore that field otherwise. We can use the [fragments](/learn/queries/#fragments) to do this. By setting up a fragment defined on `Droid` and including it in the selection set, we ensure that we only query for `primaryFunction` where it is defined:
125
69
126
70
```graphql
127
71
# { "graphiql": true }
128
-
{
72
+
query{
129
73
hero {
130
74
name
131
75
...DroidFields
@@ -137,15 +81,11 @@ fragment DroidFields on Droid {
137
81
}
138
82
```
139
83
140
-
This query is valid, but it's a bit verbose; named fragments were valuable
141
-
above when we used them multiple times, but we're only using this one once.
142
-
Instead of using a named fragment, we can use an inline fragment; this
143
-
still allows us to indicate the type we are querying on, but without naming
144
-
a separate fragment:
84
+
This query is valid, but it's a bit verbose; named fragments were valuable above when we used them multiple times, but we're only using this one once. Instead of using a named fragment, we can use an [inline fragment](/learn/queries/#inline-fragments); this still allows us to indicate the type we are querying on, but without naming a separate fragment:
145
85
146
86
```graphql
147
87
# { "graphiql": true }
148
-
{
88
+
query{
149
89
hero {
150
90
name
151
91
...onDroid {
@@ -155,10 +95,65 @@ a separate fragment:
155
95
}
156
96
```
157
97
158
-
This has just scratched the surface of the validation system; there
159
-
are a number of validation rules in place to ensure that a GraphQL query
160
-
is semantically meaningful. The specification goes into more detail about this
directory in GraphQL.js contains code implementing a
164
-
specification-compliant GraphQL validator.
98
+
### Cyclic fragment spreads
99
+
100
+
To start, let's take a complex valid query. This is a nested query, but with the duplicated fields factored out into a fragment:
101
+
102
+
```graphql
103
+
# { "graphiql": true }
104
+
query {
105
+
hero {
106
+
...NameAndAppearances
107
+
friends {
108
+
...NameAndAppearances
109
+
friends {
110
+
...NameAndAppearances
111
+
}
112
+
}
113
+
}
114
+
}
115
+
116
+
fragmentNameAndAppearancesonCharacter {
117
+
name
118
+
appearsIn
119
+
}
120
+
```
121
+
122
+
And this query is valid. Let's take a look at some invalid queries...
123
+
124
+
A fragment cannot refer to itself or create a cycle, as this could result in an unbounded result! Here's the same query above but without the explicit three levels of nesting:
125
+
126
+
```graphql
127
+
# { "graphiql": true }
128
+
query {
129
+
hero {
130
+
...NameAndAppearancesAndFriends
131
+
}
132
+
}
133
+
134
+
fragmentNameAndAppearancesAndFriendsonCharacter {
135
+
name
136
+
appearsIn
137
+
friends {
138
+
...NameAndAppearancesAndFriends
139
+
}
140
+
}
141
+
```
142
+
143
+
This has just scratched the surface of the validation system; there are a number of validation rules in place to ensure that a GraphQL operation is semantically meaningful. The specification goes into more detail about this topic in the [validation section](https://spec.graphql.org/draft/#sec-Validation), and the [validation directory](https://github.com/graphql/graphql-js/blob/main/src/validation) in GraphQL.js contains code implementing a specification-compliant GraphQL validator.
144
+
145
+
## Validation errors
146
+
147
+
As we have seen in the examples above, when a GraphQL server encounters a validation error in a request, it will return information about what happened in the `errors` key of the response. Specifically, when GraphQL detects a validation issue in a document, it raises a _request error_ before execution begins, meaning that no partial data will be included in the response.
148
+
149
+
And because the GraphQL specification requires all implementations to validate incoming requests against the schema, developers won't need to write specific runtime logic to handle these validation issues manually.
150
+
151
+
## Next steps
152
+
153
+
To recap what we've learned about validation:
154
+
155
+
- The GraphQL documents that clients submit in their requests must be syntactically correct and considered valid when checked against the schema
156
+
- The GraphQL specification requires that implementations check that incoming requests contain valid field selections, correct fragment usage, and more
157
+
- When a validation issue occurs, the server will raise a request error and return information about what happened to the client before field execution occurs
158
+
159
+
Head over to the [Execution](/learn/execution/) page to learn how GraphQL provides data for each field in a request after the validation step is complete.
0 commit comments