Error Handling
Whenever you execute a GraphQL operation, two high-level types of errors can occur:
Execution errors: a GraphQL response wasn't received because an error occurred during request execution. This could be a networking error (SSL, socket, HTTP), a client-side error (response parsing failure, invalid cache data), or other execution failures. When an execution error occurs, no data is returned.
GraphQL errors: a GraphQL response is received, and it contains a non-empty
errorsfield. 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.
Execution errors
Execution errors are thrown as exceptions that you can catch in a do/catch block. These errors indicate a fatal error and terminate execution of the operation.
1do {
2 let response = try await apollo.fetch(query: HeroNameQuery())
3 // Handle successful response
4 print(response.data?.hero?.name)
5} catch {
6 // Execution error (networking, parsing, cache, etc.)
7 print("Error executing operation: \(error)")
8}Causes
Possible causes of an execution error include (but are not limited to):
Networking errors:
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.
Client-side errors:
The response JSON could not be parsed into a valid response model for the operation.
File I/O failed while reading cache data.
Invalid cache data was encountered.
GraphQL errors
Because a response with GraphQL errors might still contain data, an execution error is not thrown. Instead, a successful response is returned containing a GraphQLResponse 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, GraphQLResponse.data may be nil if everything else is non-nullable.
Apollo iOS gives you access to both the data and the errors in the GraphQLResponse:
1do {
2 let response = try await apollo.fetch(query: FilmAndPersonQuery())
3
4 if let errors = response.errors {
5 // GraphQL errors - handle these as needed
6 print("GraphQL errors: \(errors)")
7 }
8
9 let film = response.data?.film // Exists
10 let person = response.data?.person // nil
11
12} catch {
13 // Execution error (networking, parsing, cache, etc.)
14 print("Error executing operation: \(error)")
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.