Error handling
ApolloResponse
Use ApolloResponse.data
to check if the server returned data:
if (response.data != null) {// Handle (potentially partial) data} else {// Something wrong happenedif (response.exception != null) {// Handle non-GraphQL errors} else {// Handle GraphQL errors in response.errors}}
This is also true when calling toFlow()
(e.g. with subscriptions) and watch()
(with the normalized cache).
apolloClient.subscription(subscription).toFlow().collect { response ->if (response.data != null) {// Handle (potentially partial) data} else {if (response.exception != null) {// Handle non-GraphQL errors} else {// Handle GraphQL errors in response.errors}}}
If you prefer throwing, you can use dataOrThrow()
to get a non-null data:
val data = apolloClient.query(ExampleQuery()).execute().dataOrThrow()// data is non-null
Different types of errors
Whenever you execute a GraphQL operation with Apollo Kotlin (or any other GraphQL client), two types of errors can occur:
- Fetch 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 fetch error occurs, no data is returned and
response.exception
is non-null. - GraphQL errors: a GraphQL response is received (HTTP 200), 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.
Fetch errors
Fetch errors happen when it's impossible to fetch a GraphQL response. They can have a wide variety of causes (non-exhaustive list):
- 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 CacheOnly but the data wasn't cached.
- And more...
You can display an error based on the exception in response.exception
GraphQL errors
GraphQL errors happen when a GraphQL response is successfully fetched but contains GraphQL errors. In that case, the response may contain partial data.
For example, the following query uses an invalid id
to look up a Person
:
query FilmAndPersonQuery {film(id: "ZmlsbXM6MQ==") {title}person(id: "badId") {name}}
The server will return the following response:
{"data": {"film": {"title": "A New Hope"},"person": null},"errors": [{"message": "Cannot find person with id 'badId'","path": ["person"]}]}
person
is null:
// there was an error fetching dataprintln(response.data?.person) // null// read the error from response.errorsprintln(response.errors?.first()?.message) // "Cannot find person with id 'badId'"// partial data is also returnedprintln(response.data?.film?.title) // "A New Hope"// exception is nullprintln(response.exception) // null
This allows to display as much data as possible without having to do a new network round trip.
Because GraphQL models both errors and semantic nulls as nullable fields, you must check errors
to determine whether the field is an error or a true null.
For an example, it is possible for a person to not have a starship:
{"data": {"person": {"starship": null}}}
In that case, starship
is a true null and not an error.
Handling GraphQL errors at parsing time
Because making the difference between true nulls and error nulls is cumbersome, Apollo Kotlin offers a way to handle errors automatically at parsing time. Fields that are nullable only for error purposes can also be generated as non-null in Kotlin. Read "handling nullability" for more details.