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.

Swift
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}
Swift
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:

GraphQL
1query FilmAndPersonQuery {
2  film(id: "ZmlsbXM6M") {
3    title
4  }
5  person(id: "badId") {
6    name
7  }
8}

The server will send the following response:

JSON
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:

Swift
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.

Feedback

Edit on GitHub

Forums