Error Handling
Whenever you execute a GraphQL operation with two high-level types of errors can occur:
Network errors: a GraphQL response wasn't received because an error occurred while communicating with your GraphQL server. This might be an SSL error, a socket error because your app is offline, or a 500 or any other HTTP error. When a network error occurs, no data is returned.
GraphQL errors: a GraphQL response is received, and it contains a non-empty
errors
field. This means the server wasn't able to completely process the query. The response might include partial data if the server was able to process some of the query.
Network errors
The result of executing an operation is a Swift Result
. A network error results in a .failure(Error)
result for the operation.
You can handle network errors by using a do/catch
block and calling try result.get()
or by switching on the result
.
1apollo.fetch(query: HeroNameQuery()) { result in
2 do {
3 let data = try result.get().data
4 ...
5
6 } catch {
7 // Network error
8 print(error)
9 }
10}
1apollo.fetch(query: HeroNameQuery()) { result in
2 switch result {
3 case .success(let response):
4 ...
5
6 case .failure(let error):
7 // Network error
8 print(error)
9 }
10}
Causes
Possible causes of a network error include (but are not limited to):
The app is offline or doesn't have access to the network.
A DNS error occurred, making it impossible to look up the host.
An SSL error occurred (e.g., the server certificate isn't trusted).
The connection was closed.
The server responded with a non-successful HTTP code.
The server didn't respond with valid JSON.
The response JSON doesn't satisfy the schema and cannot be parsed.
A request was specified as
.returnCacheDataDontFetch
but the data wasn't cached.
Examine the exception for more detailed information about the actual error.
GraphQL errors
Because a response with GraphQL errors might still contain data, a .failure
result is not returned. Instead, they return a .success
result containing a GraphQLResult
whose errors
field contains the errors that occurred.
For example, the following query uses an invalid id
to look up a Person
:
1query FilmAndPersonQuery {
2 film(id: "ZmlsbXM6M") {
3 title
4 }
5 person(id: "badId") {
6 name
7 }
8}
The server will send the following response:
1{
2 "data": {
3 "film": {
4 "title": "A New Hope"
5 },
6 "person": null
7 },
8 "errors": [
9 {
10 "message": "No entry in local cache for https://swapi.dev/api/people/m�H/",
11 "locations": [
12 {
13 "line": 35,
14 "column": 3
15 }
16 ],
17 "path": [
18 "person"
19 ]
20 }
21 ]
22}
Note that while there are errors, the query successfully returned the title of the film: A New Hope
. In general, any error while executing an operation bubbles up to the next nullable field. In this case data?.person
is nil
. In the worst case, GraphQLResult.data
may be nil
if everything else is non-nullable.
Apollo iOS gives you access to both the data
and the errors
in the GraphQLResult
class:
1apollo.fetch(query: HeroNameQuery()) { result in
2 switch result {
3 case .success(let response):
4 if let errors = response.errors {
5 // GraphQL errors
6 }
7
8 let film = response.data?.film // Exists
9 let person = response.data?.person // nil
10
11 case .failure(let error):
12 // Network error
13 print(error)
14 }
15}
GraphQL errors are returned as type-safe GraphQLError
values. These values are parsed from the response as described in the section on response format errors in the GraphQL specification.