Repository: apollographql/apollo-kotlin
Pull request #4836 (2023-04-04 18:35:35)

Error handling take #n
New take on error handling, supersedes #4800 and #4696

No more `ignorePartialData`, the reasonning is that checks should be done on `data != null`:

```kotlin
val response = apolloClient.query(query).execute()

// having to create an intermediate variable is unfortunate but needed to have smart cast
// See https://youtrack.jetbrains.com/issue/KT-8819/
val data = response.data
if (data != null) {
  // do something with data
} else {
  // do something with exception
}
```

If you prefer throwing, use `dataOrThrow()`:

```kotlin
// data is non-null
val data = apolloClient.query(query).execute().dataOrThrow()
```

Details

- Revert "hide setters, they should have been hidden from day1 (#4769)"
- Revert "Add ApolloClient.ignorePartialData (#4725)"
- make ApolloException sealed
- deprecate dataAssertNoError
- make sure `data == null` implies `exception ! = null`
- update apiDump


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *apollo-android-docs* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 4f430f611862efca2561a3be2552058563dabc4d |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/apollo-android-docs/deploys/642c6df948867c0007bd20d6 |

Patch:
diff --git a/docs/source/essentials/errors.mdx b/docs/source/essentials/errors.mdx
index 280f0a8b91..8f194c3dfa 100644
--- a/docs/source/essentials/errors.mdx
+++ b/docs/source/essentials/errors.mdx
@@ -2,20 +2,29 @@
 title: Error handling
 ---
 
-Whenever you execute a GraphQL operation with Apollo Kotlin (or any other GraphQL client), 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`](https://spec.graphql.org/draft/#sec-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
-
-Network errors are surfaced in the `ApolloResponse.exception` field.
+You can use `response.data` to check if the server returned valid data:
 
 ```kotlin
-val response = apolloClient.query(query).execute()
-if (response.exception != null) {
-  // handle exception here
+val response = apolloClient.query(ExampleQuery()).execute()
+// Using 'data' to be able to do a smart cast below (KT-8819)
+val data = response.data
+
+when {
+  data != null -> {
+    // data can be smart cast to non-null here
+    println("The server returned data: $data")
+  }
+  else -> {
+    // an error happened, check response.exception for more details or just display a generic error 
+    when (response.exception) {
+      is ApolloGraphQLException -> // do something with exception.errors
+      is ApolloHttpException -> // do something with exception.statusCode
+      is ApolloNetworkException -> TODO()
+      is ApolloParseException -> TODO()
+      else -> // generic error
+    }
+  }
 }
 ```
 
@@ -23,30 +32,29 @@ This is also true when calling `toFlow()` (e.g. with [subscriptions](../essentia
 
 ```kotlin
 apolloClient.subscription(subscription).toFlow().collect { response ->
-  if (response.exception != null) {
-    // handle network errors
+  if (response.data != null) {
+    // handle data
+  } else {
+    // handle exceptions
   }
 }
 ```
 
-### Causes
+If you prefer throwing, you can use `dataOrThrow()` to get a non-null data:
 
-Possible causes of a network error include (but are not limited to):
+```kotlin
+val data = apolloClient.query(ExampleQuery()).execute().dataOrThrow()
+// data is non-null
+```
 
-* 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.
+## Different types of errors
 
-Examine the exception for more detailed information about the actual error.
+Whenever you execute a GraphQL operation with Apollo Kotlin (or any other GraphQL client), two high-level types of errors can occur:
 
-## GraphQL errors
+* **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`](https://spec.graphql.org/draft/#sec-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.
 
-Because GraphQL errors might still contain data, they do _not_ throw. Instead, they return a `Response` with a `Response.errors` field indicating the errors that occurred.
+### GraphQL errors
 
 For example, the following query uses an invalid `id` to look up a `Person`:
 
@@ -90,55 +98,65 @@ The server will send the following response:
 
 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](https://spec.graphql.org/draft/#sec-Errors) to the next nullable field. In this case, `person` is nullable. In the worst case, `response.data` can be null if everything else is non-nullable.
 
-Apollo Kotlin gives you access to both the data and the errors in the `Response` class:
+When GraphQL errors happen, `ApolloResponse.exception` will be an instance of `ApolloGraphQLException` and you can use `exception.errors` to read the actual GraphQL errors.
 
-```kotlin
-val response = apolloClient.query(query).execute()
-if (response.exception != null) {
-  // Network error, not much to do
-  throw response.exception
-}
+### Network errors
 
-// It's possible to display the film title
-val title = response.data?.film?.title
-if (title != null) {
-  println(title)
-}
+Network errors are more varied and can have different 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.
+* More...
 
-// The person triggered an error
-val person = response.data?.person?.name
-if (person != null) {
-  // do something with response.errors
-}
-```
 
 ## Ignoring partial data
 
-If you don't want to handle partial responses, you can simplify your error handling logic. `ApolloResponse.dataAssertNoErrors` returns a non-nullable `data` and throws if there are any errors. This way, you can handle all errors in a single `catch {}` block:
+Because errors may happen on any field in your query, your UI code needs to handle any nullable field. In the example above, data.person will be `null`: 
 
-```kotlin
-val data = try {
-  apolloClient.query(query).execute().dataAssertNoErrors
-} catch (exception: ApolloException) {
-  // All network or GraphQL errors are handled here
-  throw exception
+```graphql
+query FilmAndPersonQuery {
+  # wrong id here, null will be returned
+  person(id: "badId") {
+    name
+  }
 }
+```
 
-// No need for safe calls on data
-val title = data.film?.title
+Your UI code needs to check for null:
+
+```kotlin
+if (data.person != null) {
+  // display person
+}
 ```
 
-Note that the safe call is still required on `film` because this field has a nullable type in the GraphQL schema. There are ways to override this in codegen. For more details, learn about [the `@nonnull` directive](../advanced/nonnull).
+If you prefer to catch these errors at parsing time, you can make `data.person` non-nullable using [the `@nonnull` directive](../advanced/nonnull):
 
-Another option is to call `ignorePartialData(true)`. This will force `ApolloResponse.data` to be null even if it wasn't in the response, whenever there are errors. This can also simplify error handling:
+```graphql
+extend type Query @nonnull(fields: "person")
+```
+
+Alternatively, you can check for errors in an interceptor and force data to null whenever a GraphQL error happens: 
 
 ```kotlin
-val data = apolloClient.query(query).ignorePartialData(true).execute().data
-if (data == null) {
-  // All network or GraphQL errors are handled here
-} else {
-  // No errors
-  val title = data.film?.title
+object ignorePartialDataInterceptor: ApolloInterceptor {
+  override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
+    return chain.proceed(request).map {
+      if (it.exception is ApolloGraphQLException) {
+        // nullify data altogether
+        it.newBuilder().data(null).build()
+      } else {
+        it
+      }
+    }
+  }
 }
 ```
-This can also be set globally with `ApolloClient.Builder.ignorePartialData(true)`.
+
+Note that the null check is still required on `person` because this field has a nullable type in the GraphQL schema.
diff --git a/docs/source/migration/4.0.mdx b/docs/source/migration/4.0.mdx
index 13dc25ee72..37d7927f5f 100644
--- a/docs/source/migration/4.0.mdx
+++ b/docs/source/migration/4.0.mdx
@@ -63,6 +63,7 @@ client.subscription(MySubscription()).toFlow().collect { response ->
   }
 }
 ```
+
 ### Exception folding when using the cache
 
 In v3, when using the normalized cache, you could set `emitCacheMisses` to `true` to emit cache misses instead of throwing.
diff --git a/libraries/apollo-api/api/apollo-api.api b/libraries/apollo-api/api/apollo-api.api
index f74141e285..748e49dee8 100644
--- a/libraries/apollo-api/api/apollo-api.api
+++ b/libraries/apollo-api/api/apollo-api.api
@@ -62,13 +62,12 @@ public final class com/apollographql/apollo3/api/ApolloOptionalAdapter : com/apo
 }
 
 public final class com/apollographql/apollo3/api/ApolloRequest : com/apollographql/apollo3/api/ExecutionOptions {
-	public synthetic fun <init> (Lcom/apollographql/apollo3/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo3/api/ExecutionContext;Lcom/apollographql/apollo3/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public synthetic fun <init> (Lcom/apollographql/apollo3/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo3/api/ExecutionContext;Lcom/apollographql/apollo3/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun getCanBeBatched ()Ljava/lang/Boolean;
 	public fun getEnableAutoPersistedQueries ()Ljava/lang/Boolean;
 	public fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public final fun getOperation ()Lcom/apollographql/apollo3/api/Operation;
 	public final fun getRequestUuid ()Ljava/util/UUID;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
@@ -93,15 +92,12 @@ public final class com/apollographql/apollo3/api/ApolloRequest$Builder : com/apo
 	public fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
 	public fun getSendDocument ()Ljava/lang/Boolean;
 	public fun httpHeaders (Ljava/util/List;)Lcom/apollographql/apollo3/api/ApolloRequest$Builder;
 	public synthetic fun httpHeaders (Ljava/util/List;)Ljava/lang/Object;
 	public fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Lcom/apollographql/apollo3/api/ApolloRequest$Builder;
 	public synthetic fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Ljava/lang/Object;
-	public fun ignorePartialData (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/api/ApolloRequest$Builder;
-	public synthetic fun ignorePartialData (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public final fun requestUuid (Ljava/util/UUID;)Lcom/apollographql/apollo3/api/ApolloRequest$Builder;
 	public fun sendApqExtensions (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/api/ApolloRequest$Builder;
 	public synthetic fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object;
@@ -120,12 +116,15 @@ public final class com/apollographql/apollo3/api/ApolloResponse {
 	public final field requestUuid Ljava/util/UUID;
 	public synthetic fun <init> (Ljava/util/UUID;Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/Operation$Data;Ljava/util/List;Lcom/apollographql/apollo3/exception/ApolloException;Ljava/util/Map;Lcom/apollographql/apollo3/api/ExecutionContext;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public final fun dataAssertNoErrors ()Lcom/apollographql/apollo3/api/Operation$Data;
+	public final fun dataOrThrow ()Lcom/apollographql/apollo3/api/Operation$Data;
 	public final fun hasErrors ()Z
 	public final fun newBuilder ()Lcom/apollographql/apollo3/api/ApolloResponse$Builder;
 }
 
 public final class com/apollographql/apollo3/api/ApolloResponse$Builder {
 	public fun <init> (Lcom/apollographql/apollo3/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo3/api/Operation$Data;)V
+	public fun <init> (Lcom/apollographql/apollo3/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo3/api/Operation$Data;Ljava/util/List;Ljava/util/Map;)V
+	public fun <init> (Lcom/apollographql/apollo3/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo3/exception/ApolloException;)V
 	public final fun addExecutionContext (Lcom/apollographql/apollo3/api/ExecutionContext;)Lcom/apollographql/apollo3/api/ApolloResponse$Builder;
 	public final fun build ()Lcom/apollographql/apollo3/api/ApolloResponse;
 	public final fun data (Lcom/apollographql/apollo3/api/Operation$Data;)Lcom/apollographql/apollo3/api/ApolloResponse$Builder;
@@ -555,7 +554,6 @@ public abstract interface class com/apollographql/apollo3/api/ExecutionOptions {
 	public abstract fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public abstract fun getHttpHeaders ()Ljava/util/List;
 	public abstract fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public abstract fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public abstract fun getSendApqExtensions ()Ljava/lang/Boolean;
 	public abstract fun getSendDocument ()Ljava/lang/Boolean;
 }
@@ -637,7 +635,6 @@ public abstract interface class com/apollographql/apollo3/api/MutableExecutionOp
 	public abstract fun enableAutoPersistedQueries (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public abstract fun httpHeaders (Ljava/util/List;)Ljava/lang/Object;
 	public abstract fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Ljava/lang/Object;
-	public abstract fun ignorePartialData (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public abstract fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public abstract fun sendDocument (Ljava/lang/Boolean;)Ljava/lang/Object;
 }
@@ -1162,15 +1159,19 @@ public final class com/apollographql/apollo3/exception/ApolloCompositeException
 	public fun <init> (Ljava/util/List;)V
 }
 
-public class com/apollographql/apollo3/exception/ApolloException : java/lang/RuntimeException {
-	public fun <init> ()V
-	public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
+public abstract class com/apollographql/apollo3/exception/ApolloException : java/lang/RuntimeException {
 	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
 }
 
 public final class com/apollographql/apollo3/exception/ApolloExceptionHandlerKt {
 }
 
+public final class com/apollographql/apollo3/exception/ApolloGraphQLException : com/apollographql/apollo3/exception/ApolloException {
+	public fun <init> (Ljava/util/List;)V
+	public final fun getErrors ()Ljava/util/List;
+}
+
 public final class com/apollographql/apollo3/exception/ApolloHttpException : com/apollographql/apollo3/exception/ApolloException {
 	public fun <init> (ILjava/util/List;Lokio/BufferedSource;Ljava/lang/String;Ljava/lang/Throwable;)V
 	public synthetic fun <init> (ILjava/util/List;Lokio/BufferedSource;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -1213,6 +1214,12 @@ public final class com/apollographql/apollo3/exception/CacheMissException : com/
 public final class com/apollographql/apollo3/exception/CacheMissException$Companion {
 }
 
+public final class com/apollographql/apollo3/exception/DefaultApolloException : com/apollographql/apollo3/exception/ApolloException {
+	public fun <init> ()V
+	public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+}
+
 public final class com/apollographql/apollo3/exception/HttpCacheMissException : com/apollographql/apollo3/exception/ApolloException {
 	public fun <init> (Ljava/lang/String;Ljava/lang/Exception;)V
 	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Exception;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloRequest.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloRequest.kt
index 7569e556b7..8eb1042361 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloRequest.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloRequest.kt
@@ -21,7 +21,6 @@ private constructor(
     override val sendDocument: Boolean?,
     override val enableAutoPersistedQueries: Boolean?,
     override val canBeBatched: Boolean?,
-    override val ignorePartialData: Boolean?,
 
     @ApolloInternal
     val useV3ExceptionHandling: Boolean?,
@@ -41,7 +40,6 @@ private constructor(
         .sendDocument(sendDocument)
         .enableAutoPersistedQueries(enableAutoPersistedQueries)
         .canBeBatched(canBeBatched)
-        .ignorePartialData(ignorePartialData)
         .useV3ExceptionHandling(useV3ExceptionHandling)
   }
 
@@ -98,13 +96,6 @@ private constructor(
       this.canBeBatched = canBeBatched
     }
 
-    override var ignorePartialData: Boolean? = null
-      private set
-
-    override fun ignorePartialData(ignorePartialData: Boolean?): Builder<D> = apply {
-      this.ignorePartialData = ignorePartialData
-    }
-
     private var useV3ExceptionHandling: Boolean? = null
 
     @ApolloInternal
@@ -136,7 +127,6 @@ private constructor(
           sendDocument = sendDocument,
           enableAutoPersistedQueries = enableAutoPersistedQueries,
           canBeBatched = canBeBatched,
-          ignorePartialData = ignorePartialData,
           useV3ExceptionHandling = useV3ExceptionHandling,
       )
     }
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloResponse.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloResponse.kt
index 6af908a019..86135ab1c4 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloResponse.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ApolloResponse.kt
@@ -1,12 +1,19 @@
 package com.apollographql.apollo3.api
 
 import com.apollographql.apollo3.exception.ApolloException
+import com.apollographql.apollo3.exception.ApolloGraphQLException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.benasher44.uuid.Uuid
 import kotlin.jvm.JvmField
 import kotlin.jvm.JvmName
 
 /**
- * Represents a GraphQL response. GraphQL responses can be be partial responses so it is valid to have both data != null and errors
+ * Represents a GraphQL response. GraphQL responses can be partial responses, so it is valid to have both data != null and exception != null
+ *
+ * Valid states are:
+ * - data != null && exception == null: complete data with no error
+ * - data == null && exception != null: no data, a network error or operation error happened
+ * - data != null && exception != null: partial data with field errors
  */
 class ApolloResponse<D : Operation.Data>
 private constructor(
@@ -21,7 +28,8 @@ private constructor(
 
     /**
      * Parsed response of GraphQL [operation] execution.
-     * Can be `null` in case if [operation] execution failed.
+     *
+     * See also [exception]
      */
     @JvmField
     val data: D?,
@@ -32,22 +40,14 @@ private constructor(
      *
      * If no GraphQL error was raised, [errors] is null. Else it's a non-empty list of errors indicating where the error(s) happened.
      *
-     * Note that because GraphQL allows partial data, it is possible to have both [data] non null and [errors] non null.
+     * Note that because GraphQL allows partial data, it is possible to have both [data] non-null and [errors] non-null.
      *
-     * See also [exception] for exceptions happening before a valid GraphQL response could be received.
+     * See also [exception]
      */
     @JvmField
     val errors: List<Error>?,
 
-    /**
-     * An [ApolloException] if a valid GraphQL response wasn't received or `null` if a valid GraphQL response was received.
-     * For example, `exception` is non null if there is a network failure or cache miss.
-     * If `exception` is non null, [data] and [errors] will be null.
-     *
-     * See also [errors] for GraphQL errors returned by the server.
-     */
-    @JvmField
-    val exception: ApolloException?,
+    exception: ApolloException?,
 
     /**
      * Extensions of GraphQL protocol, arbitrary map of key [String] / value [Any] sent by server along with the response.
@@ -78,6 +78,22 @@ private constructor(
     val isLast: Boolean,
 ) {
 
+  /**
+   * An [ApolloException] if a complete GraphQL response wasn't received, an instance of [ApolloGraphQLException] if GraphQL
+   * errors were return or another instance of [ApolloException] if a network, parsing, caching or other error happened.
+   *
+   * For example, `exception` is non-null if there is a network failure or cache miss.
+   *
+   * See also [data]
+   */
+  @JvmField
+  val exception: ApolloException? = when  {
+    exception != null -> exception
+    !errors.isNullOrEmpty() -> ApolloGraphQLException(errors)
+    data == null -> DefaultApolloException("No data and no error was returned")
+    else -> null
+  }
+
   /**
    * A shorthand property to get a non-nullable `data` if handling partial data is **not** important
    *
@@ -85,41 +101,76 @@ private constructor(
    * to implement something like `ApolloResponse<D>.assertNoErrors(): ApolloResponse<D & Any>`
    */
   @get:JvmName("dataAssertNoErrors")
+  @Deprecated(message = "Use dataOrThrow instead", replaceWith = ReplaceWith("dataOrThrow()"))
   val dataAssertNoErrors: D
     get() {
-      return when {
-        exception != null -> throw exception
-        hasErrors() -> throw ApolloException("The response has errors: $errors")
-        else -> data ?: throw ApolloException("The server did not return any data")
-      }
+      return dataOrThrow()
     }
 
+  /**
+   * Return [data] if not null or throws [exception] else
+   */
+  fun dataOrThrow(): D = data ?: throw exception!!
+
   fun hasErrors(): Boolean = !errors.isNullOrEmpty()
 
   fun newBuilder(): Builder<D> {
-    return Builder(operation, requestUuid, data)
-        .errors(errors)
-        .exception(exception)
-        .extensions(extensions)
+    return Builder(operation, requestUuid, data, errors, extensions, exception)
         .addExecutionContext(executionContext)
         .isLast(isLast)
   }
 
-  class Builder<D : Operation.Data>(
+  class Builder<D : Operation.Data> internal constructor(
       private val operation: Operation<D>,
       private var requestUuid: Uuid,
       private var data: D?,
+      private var errors: List<Error>?,
+      private var extensions: Map<String, Any?>?,
+      private var exception: ApolloException?
   ) {
     private var executionContext: ExecutionContext = ExecutionContext.Empty
-    private var errors: List<Error>? = null
-    private var exception: ApolloException? = null
-    private var extensions: Map<String, Any?>? = null
     private var isLast = false
 
+    /**
+     * Constructs a successful response with a valid data, no errors nor extensions
+     */
+    constructor(
+        operation: Operation<D>,
+        requestUuid: Uuid,
+        data: D,
+    ): this(operation, requestUuid, data, null, null, null)
+
+    /**
+     * Constructs a response from data, errors and extensions
+     *
+     * If there are GraphQL errors, they will also be forwarded to [exception] so that the caller can do all the
+     * checking in a single place
+     */
+    constructor(
+        operation: Operation<D>,
+        requestUuid: Uuid,
+        data: D?,
+        errors: List<Error>?,
+        extensions: Map<String, Any?>?,
+    ): this(operation, requestUuid, data, errors, extensions, null)
+
+    /**
+     * Constructs an exception response
+     */
+    constructor(
+        operation: Operation<D>,
+        requestUuid: Uuid,
+        exception: ApolloException
+    ): this(operation, requestUuid, null, null, null, exception)
+
     fun addExecutionContext(executionContext: ExecutionContext) = apply {
       this.executionContext = this.executionContext + executionContext
     }
 
+    fun data(data: D?) = apply {
+      this.data = data
+    }
+
     fun errors(errors: List<Error>?) = apply {
       this.errors = errors
     }
@@ -136,16 +187,11 @@ private constructor(
       this.requestUuid = requestUuid
     }
 
-    fun data(data: D?) = apply {
-      this.data = data
-    }
-
     fun isLast(isLast: Boolean) = apply {
       this.isLast = isLast
     }
 
     fun build(): ApolloResponse<D> {
-      @Suppress("DEPRECATION")
       return ApolloResponse(
           operation = operation,
           requestUuid = requestUuid,
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt
index a64e322a96..c2cef4ded5 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt
@@ -2,6 +2,7 @@
 package com.apollographql.apollo3.api
 
 import com.apollographql.apollo3.exception.ApolloException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.contract
 import kotlin.jvm.JvmName
@@ -11,6 +12,6 @@ import kotlin.jvm.JvmName
  */
 fun checkFieldNotMissing(value: Any?, name: String) {
   if (value == null) {
-    throw ApolloException("Field $name is missing")
+    throw DefaultApolloException("Field $name is missing")
   }
 }
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ExecutionOptions.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ExecutionOptions.kt
index 9c956047ec..93aabfee8f 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ExecutionOptions.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/ExecutionOptions.kt
@@ -45,12 +45,6 @@ interface ExecutionOptions {
    */
   val canBeBatched: Boolean?
 
-  /**
-   * Whether to ignore partial data.
-   * Used by [com.apollographql.apollo3.ApolloClient]
-   */
-  val ignorePartialData: Boolean?
-
   companion object {
     /**
      * Used by [com.apollographql.apollo3.network.http.BatchingHttpInterceptor]
@@ -88,23 +82,4 @@ interface MutableExecutionOptions<T> : ExecutionOptions {
   fun enableAutoPersistedQueries(enableAutoPersistedQueries: Boolean?): T
 
   fun canBeBatched(canBeBatched: Boolean?): T
-
-  /**
-   * Configures whether partial data should be ignored.
-   *
-   * If true, responses with errors will always be surfaced with a null [ApolloResponse.data] even if the received data was not null.
-   * This can simplify error handling at the call site, if you don't care about partial data. E.g.:
-   *
-   * ```
-   * val response = apolloClient.query(query).ignorePartialData(true).execute()
-   * if (response.data == null) {
-   *   // There were network or GraphQL error(s)
-   * } else {
-   *   // No errors
-   * }
-   * ```
-   *
-   * Default: false
-   */
-  fun ignorePartialData(ignorePartialData: Boolean?): T
 }
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt
index 40aac89c9d..11e6bd3ef7 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt
@@ -19,7 +19,7 @@ internal object ResponseParser {
       jsonReader: JsonReader,
       operation: Operation<D>,
       customScalarAdapters: CustomScalarAdapters,
-  ): ApolloResponse<D>  {
+  ): ApolloResponse<D> {
     @Suppress("NAME_SHADOWING")
     return jsonReader.use { jsonReader ->
       jsonReader.beginObject()
@@ -39,9 +39,7 @@ internal object ResponseParser {
 
       jsonReader.endObject()
 
-      ApolloResponse.Builder(requestUuid = uuid4(), operation = operation, data = data).errors(errors)
-          .extensions(extensions)
-          .build()
+      ApolloResponse.Builder(requestUuid = uuid4(), operation = operation, data = data, errors = errors, extensions = extensions).build()
     }
   }
 
@@ -79,12 +77,15 @@ internal object ResponseParser {
         "locations" -> {
           locations = readErrorLocations()
         }
+
         "path" -> {
           path = readPath()
         }
+
         "extensions" -> {
           extensions = readAny() as? Map<String, Any?>?
         }
+
         else -> {
           if (nonStandardFields == null) nonStandardFields = mutableMapOf()
           nonStandardFields[name] = readAny()
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
index 596472085d..5374d8e8b2 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
@@ -3,6 +3,7 @@ package com.apollographql.apollo3.exception
 
 import com.apollographql.apollo3.annotations.ApolloExperimental
 import com.apollographql.apollo3.annotations.ApolloInternal
+import com.apollographql.apollo3.api.Error
 import com.apollographql.apollo3.api.http.HttpHeader
 import okio.BufferedSource
 
@@ -11,7 +12,12 @@ import okio.BufferedSource
  *
  * This inherits from [RuntimeException]. Java callers will have to explicitly catch all [ApolloException]s.
  */
-open class ApolloException(message: String? = null, cause: Throwable? = null) : RuntimeException(message, cause)
+sealed class ApolloException(message: String? = null, cause: Throwable? = null) : RuntimeException(message, cause)
+
+/**
+ * A generic exception when no additional context exists
+ */
+class DefaultApolloException(message: String? = null, cause: Throwable? = null): ApolloException(message, cause)
 
 /**
  * A network error happened: socket closed, DNS issue, TLS problem, etc...
@@ -90,6 +96,8 @@ class JsonDataException(message: String) : ApolloException(message)
  */
 class ApolloParseException(message: String? = null, cause: Throwable? = null) : ApolloException(message = message, cause = cause)
 
+class ApolloGraphQLException(val errors: List<Error>): ApolloException("GraphQL error(s)")
+
 /**
  * An object/field was missing in the cache
  * If [fieldName] is null, it means a reference to an object could not be resolved
diff --git a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
index adc0bb979b..39cfbe90a8 100644
--- a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
+++ b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
@@ -8,6 +8,7 @@ import com.apollographql.apollo3.api.Operation
 import com.apollographql.apollo3.api.Query
 import com.apollographql.apollo3.exception.ApolloException
 import com.apollographql.apollo3.exception.CacheMissException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.interceptor.ApolloInterceptor
 import com.apollographql.apollo3.interceptor.ApolloInterceptorChain
 import kotlinx.coroutines.flow.Flow
@@ -164,7 +165,7 @@ internal val FetchPolicyRouterInterceptor = object : ApolloInterceptor {
         // If we haven't emitted anything, send a composite exception
         val first = exceptions.firstOrNull()
         val exception = if (first == null) {
-          ApolloException("No response emitted")
+          DefaultApolloException("No response emitted")
         } else {
           first.also { firstException ->
             exceptions.drop(1).forEach {
@@ -173,8 +174,7 @@ internal val FetchPolicyRouterInterceptor = object : ApolloInterceptor {
           }
         }
         emit(
-            ApolloResponse.Builder(request.operation, request.requestUuid, null)
-                .exception(exception)
+            ApolloResponse.Builder(request.operation, request.requestUuid, exception)
                 .build()
 
         )
diff --git a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
index 12d347ea73..c71135985c 100644
--- a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
+++ b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
@@ -22,6 +22,7 @@ import com.apollographql.apollo3.cache.normalized.storeReceiveDate
 import com.apollographql.apollo3.cache.normalized.writeToCacheAsynchronously
 import com.apollographql.apollo3.exception.ApolloException
 import com.apollographql.apollo3.exception.CacheMissException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.exception.apolloExceptionHandler
 import com.apollographql.apollo3.interceptor.ApolloInterceptor
 import com.apollographql.apollo3.interceptor.ApolloInterceptorChain
@@ -64,7 +65,7 @@ internal class ApolloCacheInterceptor(
     if (request.doNotStore) {
       return
     }
-    if (response.exception != null) {
+    if (response.data == null) {
       return
     }
     if (response.hasErrors() && !request.storePartialResponses) {
@@ -159,7 +160,7 @@ internal class ApolloCacheInterceptor(
       var previousResponse: ApolloResponse<D>? = null
       networkResponses.collect { response ->
         if (optimisticData != null && previousResponse != null) {
-          throw ApolloException("Apollo: optimistic updates can only be applied with one network response")
+          throw DefaultApolloException("Apollo: optimistic updates can only be applied with one network response")
         }
         previousResponse = response
         if (optimisticKeys == null) optimisticKeys = if (optimisticData != null) {
@@ -214,10 +215,9 @@ internal class ApolloCacheInterceptor(
       return ApolloResponse.Builder(
           requestUuid = request.requestUuid,
           operation = operation,
-          data = null,
+          exception = e,
       )
           .addExecutionContext(request.executionContext)
-          .exception(e)
           .cacheInfo(
               CacheInfo.Builder()
                   .cacheStartMillis(startMillis)
@@ -234,6 +234,8 @@ internal class ApolloCacheInterceptor(
         requestUuid = request.requestUuid,
         operation = operation,
         data = data,
+        errors = null,
+        extensions = null
     ).addExecutionContext(request.executionContext)
         .cacheInfo(
             CacheInfo.Builder()
diff --git a/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt b/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
index adc0bb979b..39cfbe90a8 100644
--- a/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
+++ b/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/FetchPolicyInterceptors.kt
@@ -8,6 +8,7 @@ import com.apollographql.apollo3.api.Operation
 import com.apollographql.apollo3.api.Query
 import com.apollographql.apollo3.exception.ApolloException
 import com.apollographql.apollo3.exception.CacheMissException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.interceptor.ApolloInterceptor
 import com.apollographql.apollo3.interceptor.ApolloInterceptorChain
 import kotlinx.coroutines.flow.Flow
@@ -164,7 +165,7 @@ internal val FetchPolicyRouterInterceptor = object : ApolloInterceptor {
         // If we haven't emitted anything, send a composite exception
         val first = exceptions.firstOrNull()
         val exception = if (first == null) {
-          ApolloException("No response emitted")
+          DefaultApolloException("No response emitted")
         } else {
           first.also { firstException ->
             exceptions.drop(1).forEach {
@@ -173,8 +174,7 @@ internal val FetchPolicyRouterInterceptor = object : ApolloInterceptor {
           }
         }
         emit(
-            ApolloResponse.Builder(request.operation, request.requestUuid, null)
-                .exception(exception)
+            ApolloResponse.Builder(request.operation, request.requestUuid, exception)
                 .build()
 
         )
diff --git a/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt b/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
index 12d347ea73..ff6fd5aff6 100644
--- a/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
+++ b/libraries/apollo-normalized-cache/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/ApolloCacheInterceptor.kt
@@ -22,6 +22,7 @@ import com.apollographql.apollo3.cache.normalized.storeReceiveDate
 import com.apollographql.apollo3.cache.normalized.writeToCacheAsynchronously
 import com.apollographql.apollo3.exception.ApolloException
 import com.apollographql.apollo3.exception.CacheMissException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.exception.apolloExceptionHandler
 import com.apollographql.apollo3.interceptor.ApolloInterceptor
 import com.apollographql.apollo3.interceptor.ApolloInterceptorChain
@@ -64,7 +65,7 @@ internal class ApolloCacheInterceptor(
     if (request.doNotStore) {
       return
     }
-    if (response.exception != null) {
+    if (response.data == null) {
       return
     }
     if (response.hasErrors() && !request.storePartialResponses) {
@@ -159,7 +160,7 @@ internal class ApolloCacheInterceptor(
       var previousResponse: ApolloResponse<D>? = null
       networkResponses.collect { response ->
         if (optimisticData != null && previousResponse != null) {
-          throw ApolloException("Apollo: optimistic updates can only be applied with one network response")
+          throw DefaultApolloException("Apollo: optimistic updates can only be applied with one network response")
         }
         previousResponse = response
         if (optimisticKeys == null) optimisticKeys = if (optimisticData != null) {
@@ -214,10 +215,9 @@ internal class ApolloCacheInterceptor(
       return ApolloResponse.Builder(
           requestUuid = request.requestUuid,
           operation = operation,
-          data = null,
+          exception = e,
       )
           .addExecutionContext(request.executionContext)
-          .exception(e)
           .cacheInfo(
               CacheInfo.Builder()
                   .cacheStartMillis(startMillis)
@@ -234,6 +234,8 @@ internal class ApolloCacheInterceptor(
         requestUuid = request.requestUuid,
         operation = operation,
         data = data,
+        errors = null,
+        extensions = null,
     ).addExecutionContext(request.executionContext)
         .cacheInfo(
             CacheInfo.Builder()
diff --git a/libraries/apollo-runtime-java/api/apollo-runtime-java.api b/libraries/apollo-runtime-java/api/apollo-runtime-java.api
index 2bc76cd737..25642e752b 100644
--- a/libraries/apollo-runtime-java/api/apollo-runtime-java.api
+++ b/libraries/apollo-runtime-java/api/apollo-runtime-java.api
@@ -45,7 +45,6 @@ public class com/apollographql/apollo3/runtime/java/ApolloClient$Builder : com/a
 	public fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
 	public fun getSendDocument ()Ljava/lang/Boolean;
 	public fun httpBatching (JIZ)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
@@ -57,8 +56,6 @@ public class com/apollographql/apollo3/runtime/java/ApolloClient$Builder : com/a
 	public fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
 	public synthetic fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Ljava/lang/Object;
 	public fun httpServerUrl (Ljava/lang/String;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
-	public fun ignorePartialData (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
-	public synthetic fun ignorePartialData (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public fun interceptors (Ljava/util/List;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
 	public fun networkTransport (Lcom/apollographql/apollo3/runtime/java/network/NetworkTransport;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
 	public fun okHttpClient (Lokhttp3/OkHttpClient;)Lcom/apollographql/apollo3/runtime/java/ApolloClient$Builder;
diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/ApolloClient.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/ApolloClient.java
index 19f176d3a6..f0bac86de7 100644
--- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/ApolloClient.java
+++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/ApolloClient.java
@@ -55,7 +55,6 @@ public class ApolloClient implements Closeable {
   private Boolean sendDocument;
   private Boolean enableAutoPersistedQueries;
   private Boolean canBeBatched;
-  private Boolean ignorePartialData;
 
   private ApolloClient(
       Executor executor,
@@ -68,8 +67,7 @@ public class ApolloClient implements Closeable {
       Boolean sendApqExtensions,
       Boolean sendDocument,
       Boolean enableAutoPersistedQueries,
-      Boolean canBeBatched,
-      Boolean ignorePartialData
+      Boolean canBeBatched
   ) {
     this.executor = executor;
     this.interceptors = interceptors;
@@ -80,7 +78,6 @@ public class ApolloClient implements Closeable {
     this.sendDocument = sendDocument;
     this.enableAutoPersistedQueries = enableAutoPersistedQueries;
     this.canBeBatched = canBeBatched;
-    this.ignorePartialData = ignorePartialData;
 
     networkInterceptor = new NetworkInterceptor(
         httpNetworkTransport,
@@ -108,8 +105,7 @@ public class ApolloClient implements Closeable {
         .httpHeaders(httpHeaders)
         .sendApqExtensions(sendApqExtensions)
         .sendDocument(sendDocument)
-        .enableAutoPersistedQueries(enableAutoPersistedQueries)
-        .ignorePartialData(ignorePartialData);
+        .enableAutoPersistedQueries(enableAutoPersistedQueries);
     if (apolloRequest.getHttpMethod() != null) {
       requestBuilder.httpMethod(apolloRequest.getHttpMethod());
     }
@@ -128,27 +124,10 @@ public class ApolloClient implements Closeable {
     if (apolloRequest.getCanBeBatched() != null) {
       requestBuilder.addHttpHeader(ExecutionOptions.CAN_BE_BATCHED, apolloRequest.getCanBeBatched().toString());
     }
-    if (apolloRequest.getIgnorePartialData() != null) {
-      requestBuilder.ignorePartialData(apolloRequest.getIgnorePartialData());
-    }
     DefaultApolloDisposable disposable = new DefaultApolloDisposable();
     ArrayList<ApolloInterceptor> interceptors = new ArrayList<>(this.interceptors);
     interceptors.add(networkInterceptor);
-
-    ApolloRequest<D> request = requestBuilder.build();
-    ApolloCallback<D> actualCallback;
-    if (request.getIgnorePartialData() == Boolean.TRUE) {
-      actualCallback = response -> {
-        if (response.hasErrors()) {
-          callback.onResponse(response.newBuilder().data(null).build());
-        } else {
-          callback.onResponse(response);
-        }
-      };
-    } else {
-      actualCallback = callback;
-    }
-    executor.execute(() -> new DefaultInterceptorChain(interceptors, 0, disposable).proceed(request, actualCallback));
+    executor.execute(() -> new DefaultInterceptorChain(interceptors, 0, disposable).proceed(requestBuilder.build(), callback));
     return disposable;
   }
 
@@ -205,7 +184,6 @@ public class ApolloClient implements Closeable {
     private Boolean sendDocument;
     private Boolean enableAutoPersistedQueries;
     private Boolean canBeBatched;
-    private Boolean ignorePartialData;
     private Boolean httpExposeErrorBody;
 
     public Builder() {
@@ -463,8 +441,7 @@ public class ApolloClient implements Closeable {
           sendApqExtensions,
           sendDocument,
           enableAutoPersistedQueries,
-          canBeBatched,
-          ignorePartialData
+          canBeBatched
       );
     }
 
@@ -545,10 +522,6 @@ public class ApolloClient implements Closeable {
       return canBeBatched;
     }
 
-    @Nullable @Override public Boolean getIgnorePartialData() {
-      return ignorePartialData;
-    }
-
     @Override public Builder addExecutionContext(@NotNull ExecutionContext executionContext) {
       this.executionContext = this.executionContext.plus(executionContext);
       return this;
@@ -589,11 +562,6 @@ public class ApolloClient implements Closeable {
       this.canBeBatched = canBeBatched;
       return this;
     }
-
-    @Override public Builder ignorePartialData(@Nullable Boolean ignorePartialData) {
-      this.ignorePartialData = ignorePartialData;
-      return this;
-    }
   }
 
   private static class ApolloDefaultExecutor implements Executor {
diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/interceptor/internal/AutoPersistedQueryInterceptor.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/interceptor/internal/AutoPersistedQueryInterceptor.java
index 567da40528..fb9f3138ab 100644
--- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/interceptor/internal/AutoPersistedQueryInterceptor.java
+++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/interceptor/internal/AutoPersistedQueryInterceptor.java
@@ -50,8 +50,7 @@ public class AutoPersistedQueryInterceptor implements ApolloInterceptor {
         if (isPersistedQueryNotFound(response.errors)) {
           continueWithDocumentRequest(chain, request, callback);
         } else if (isPersistedQueryNotSupported(response.errors)) {
-          callback.onResponse(new ApolloResponse.Builder<>(request.getOperation(), request.getRequestUuid(), null)
-              .exception(new AutoPersistedQueriesNotSupported())
+          callback.onResponse(new ApolloResponse.Builder<>(request.getOperation(), request.getRequestUuid(), new AutoPersistedQueriesNotSupported())
               .build());
         } else {
           // Cache hit
diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/internal/DefaultApolloCall.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/internal/DefaultApolloCall.java
index 1d67331247..37fcfadd57 100644
--- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/internal/DefaultApolloCall.java
+++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/internal/DefaultApolloCall.java
@@ -25,7 +25,6 @@ public class DefaultApolloCall<D extends Operation.Data> implements ApolloCall<D
   private Boolean sendDocument;
   private Boolean enableAutoPersistedQueries;
   private Boolean canBeBatched;
-  private Boolean ignorePartialData;
 
   public DefaultApolloCall(ApolloClient apolloClient, Operation<D> operation) {
     this.apolloClient = apolloClient;
@@ -41,7 +40,6 @@ public class DefaultApolloCall<D extends Operation.Data> implements ApolloCall<D
         .sendDocument(sendDocument)
         .enableAutoPersistedQueries(enableAutoPersistedQueries)
         .canBeBatched(canBeBatched)
-        .ignorePartialData(ignorePartialData)
         .build();
 
     return apolloClient.execute(apolloRequest, callback);
@@ -75,10 +73,6 @@ public class DefaultApolloCall<D extends Operation.Data> implements ApolloCall<D
     return canBeBatched;
   }
 
-  @Nullable @Override public Boolean getIgnorePartialData() {
-    return ignorePartialData;
-  }
-
   @Override public ApolloCall<D> addExecutionContext(@NotNull ExecutionContext executionContext) {
     this.executionContext = this.executionContext.plus(executionContext);
     return this;
@@ -121,9 +115,4 @@ public class DefaultApolloCall<D extends Operation.Data> implements ApolloCall<D
     this.canBeBatched = canBeBatched;
     return this;
   }
-
-  @Override public ApolloCall<D> ignorePartialData(@Nullable Boolean ignorePartialData) {
-    this.ignorePartialData = ignorePartialData;
-    return this;
-  }
 }
diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java
index defb530c9e..43201d6151 100644
--- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java
+++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java
@@ -79,8 +79,7 @@ public class HttpNetworkTransport implements NetworkTransport {
   }
 
   @NotNull private static <D extends Operation.Data> ApolloResponse<D> getExceptionResponse(@NotNull ApolloRequest<D> request, @NotNull ApolloException exception) {
-    return new ApolloResponse.Builder<>(request.getOperation(), request.getRequestUuid(), null)
-        .exception(exception)
+    return new ApolloResponse.Builder<>(request.getOperation(), request.getRequestUuid(), exception)
         .build();
   }
 
diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java
index 0359c9376d..16610ad13c 100644
--- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java
+++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java
@@ -151,8 +151,7 @@ public class WebSocketNetworkTransport implements NetworkTransport {
       if (subscriptionInfo == null) return;
       ApolloRequest<?> request = subscriptionInfo.request;
       //noinspection unchecked,rawtypes
-      subscriptionInfo.callback.onResponse(new ApolloResponse.Builder(request.getOperation(), request.getRequestUuid(), null)
-          .exception(new SubscriptionOperationException(request.getOperation().name(), payload))
+      subscriptionInfo.callback.onResponse(new ApolloResponse.Builder(request.getOperation(), request.getRequestUuid(), new SubscriptionOperationException(request.getOperation().name(), payload))
           .build());
       disposeSubscription(id);
     }
@@ -191,8 +190,7 @@ public class WebSocketNetworkTransport implements NetworkTransport {
         activeSubscriptions.clear();
         for (SubscriptionInfo subscriptionInfo : activeSubscriptionList) {
           //noinspection unchecked,rawtypes
-          subscriptionInfo.callback.onResponse(new ApolloResponse.Builder(subscriptionInfo.request.getOperation(), subscriptionInfo.request.getRequestUuid(), null)
-              .exception(networkException)
+          subscriptionInfo.callback.onResponse(new ApolloResponse.Builder(subscriptionInfo.request.getOperation(), subscriptionInfo.request.getRequestUuid(), networkException)
               .build());
           subscriptionInfo.disposable.dispose();
         }
diff --git a/libraries/apollo-runtime/api/apollo-runtime.api b/libraries/apollo-runtime/api/apollo-runtime.api
index 04517dbb4a..34cfa2ddbc 100644
--- a/libraries/apollo-runtime/api/apollo-runtime.api
+++ b/libraries/apollo-runtime/api/apollo-runtime.api
@@ -15,7 +15,6 @@ public final class com/apollographql/apollo3/ApolloCall : com/apollographql/apol
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
 	public final fun getIgnoreApolloClientHttpHeaders ()Ljava/lang/Boolean;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public final fun getOperation ()Lcom/apollographql/apollo3/api/Operation;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
 	public fun getSendDocument ()Ljava/lang/Boolean;
@@ -24,8 +23,6 @@ public final class com/apollographql/apollo3/ApolloCall : com/apollographql/apol
 	public fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Lcom/apollographql/apollo3/ApolloCall;
 	public synthetic fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Ljava/lang/Object;
 	public final fun ignoreApolloClientHttpHeaders (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloCall;
-	public fun ignorePartialData (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloCall;
-	public synthetic fun ignorePartialData (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public fun sendApqExtensions (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloCall;
 	public synthetic fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public fun sendDocument (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloCall;
@@ -35,7 +32,7 @@ public final class com/apollographql/apollo3/ApolloCall : com/apollographql/apol
 
 public final class com/apollographql/apollo3/ApolloClient : com/apollographql/apollo3/api/ExecutionOptions, java/io/Closeable {
 	public static final field Companion Lcom/apollographql/apollo3/ApolloClient$Companion;
-	public synthetic fun <init> (Lcom/apollographql/apollo3/network/NetworkTransport;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Lcom/apollographql/apollo3/network/NetworkTransport;Ljava/util/List;Lcom/apollographql/apollo3/api/ExecutionContext;Lkotlinx/coroutines/CoroutineDispatcher;Lcom/apollographql/apollo3/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lcom/apollographql/apollo3/ApolloClient$Builder;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public synthetic fun <init> (Lcom/apollographql/apollo3/network/NetworkTransport;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Lcom/apollographql/apollo3/network/NetworkTransport;Ljava/util/List;Lcom/apollographql/apollo3/api/ExecutionContext;Lkotlinx/coroutines/CoroutineDispatcher;Lcom/apollographql/apollo3/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lcom/apollographql/apollo3/ApolloClient$Builder;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun close ()V
 	public final fun executeAsFlow (Lcom/apollographql/apollo3/api/ApolloRequest;)Lkotlinx/coroutines/flow/Flow;
 	public fun getCanBeBatched ()Ljava/lang/Boolean;
@@ -44,7 +41,6 @@ public final class com/apollographql/apollo3/ApolloClient : com/apollographql/ap
 	public fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public final fun getInterceptors ()Ljava/util/List;
 	public final fun getNetworkTransport ()Lcom/apollographql/apollo3/network/NetworkTransport;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
@@ -85,7 +81,6 @@ public final class com/apollographql/apollo3/ApolloClient$Builder : com/apollogr
 	public fun getExecutionContext ()Lcom/apollographql/apollo3/api/ExecutionContext;
 	public fun getHttpHeaders ()Ljava/util/List;
 	public fun getHttpMethod ()Lcom/apollographql/apollo3/api/http/HttpMethod;
-	public fun getIgnorePartialData ()Ljava/lang/Boolean;
 	public final fun getInterceptors ()Ljava/util/List;
 	public fun getSendApqExtensions ()Ljava/lang/Boolean;
 	public fun getSendDocument ()Ljava/lang/Boolean;
@@ -101,8 +96,6 @@ public final class com/apollographql/apollo3/ApolloClient$Builder : com/apollogr
 	public fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Lcom/apollographql/apollo3/ApolloClient$Builder;
 	public synthetic fun httpMethod (Lcom/apollographql/apollo3/api/http/HttpMethod;)Ljava/lang/Object;
 	public final fun httpServerUrl (Ljava/lang/String;)Lcom/apollographql/apollo3/ApolloClient$Builder;
-	public fun ignorePartialData (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloClient$Builder;
-	public synthetic fun ignorePartialData (Ljava/lang/Boolean;)Ljava/lang/Object;
 	public final fun interceptors (Ljava/util/List;)Lcom/apollographql/apollo3/ApolloClient$Builder;
 	public final fun networkTransport (Lcom/apollographql/apollo3/network/NetworkTransport;)Lcom/apollographql/apollo3/ApolloClient$Builder;
 	public fun sendApqExtensions (Ljava/lang/Boolean;)Lcom/apollographql/apollo3/ApolloClient$Builder;
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloCall.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloCall.kt
index 30c76ded04..3367f422c8 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloCall.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloCall.kt
@@ -8,6 +8,7 @@ import com.apollographql.apollo3.api.Operation
 import com.apollographql.apollo3.api.http.HttpHeader
 import com.apollographql.apollo3.api.http.HttpMethod
 import com.apollographql.apollo3.exception.ApolloException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.toList
 
@@ -31,9 +32,7 @@ class ApolloCall<D : Operation.Data> internal constructor(
     private set
   override var canBeBatched: Boolean? = null
     private set
-  override var ignorePartialData: Boolean? = null
-    private set
-
+  
   /**
    * The HTTP headers to be sent with the request.
    * By default, these are *added* on top of any HTTP header previously set on [ApolloClient]. Call [ignoreApolloClientHttpHeaders]`(true)`
@@ -87,10 +86,6 @@ class ApolloCall<D : Operation.Data> internal constructor(
     this.canBeBatched = canBeBatched
   }
 
-  override fun ignorePartialData(ignorePartialData: Boolean?) = apply {
-    this.ignorePartialData = ignorePartialData
-  }
-
   /**
    * If set to true, the HTTP headers set on [ApolloClient] will not be used for the call, only the ones set on this [ApolloCall] will be
    * used. If set to false, both sets of headers will be concatenated and used.
@@ -111,7 +106,6 @@ class ApolloCall<D : Operation.Data> internal constructor(
         .sendDocument(sendDocument)
         .enableAutoPersistedQueries(enableAutoPersistedQueries)
         .canBeBatched(canBeBatched)
-        .ignorePartialData(ignorePartialData)
   }
 
   /**
@@ -139,7 +133,6 @@ class ApolloCall<D : Operation.Data> internal constructor(
         .sendDocument(sendDocument)
         .enableAutoPersistedQueries(enableAutoPersistedQueries)
         .canBeBatched(canBeBatched)
-        .ignorePartialData(ignorePartialData)
         .build()
     return apolloClient.executeAsFlow(request, ignoreApolloClientHttpHeaders = ignoreApolloClientHttpHeaders == true)
   }
@@ -158,7 +151,7 @@ class ApolloCall<D : Operation.Data> internal constructor(
     return when (successResponses.size) {
       0 -> {
         when (exceptionResponses.size) {
-          0 -> throw ApolloException("The operation did not emit any item, check your interceptor chain")
+          0 -> throw DefaultApolloException("The operation did not emit any item, check your interceptor chain")
           1 -> exceptionResponses.first()
           else -> {
             val first = exceptionResponses.first()
@@ -176,7 +169,7 @@ class ApolloCall<D : Operation.Data> internal constructor(
       }
 
       1 -> successResponses.first()
-      else -> throw ApolloException("The operation returned multiple items, use .toFlow() instead of .execute()")
+      else -> throw DefaultApolloException("The operation returned multiple items, use .toFlow() instead of .execute()")
     }
   }
 }
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloClient.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloClient.kt
index 25ec1ed0e1..7b829fc60d 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloClient.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/ApolloClient.kt
@@ -34,7 +34,6 @@ import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import okio.Closeable
 import kotlin.jvm.JvmOverloads
@@ -56,7 +55,6 @@ private constructor(
     override val sendDocument: Boolean?,
     override val enableAutoPersistedQueries: Boolean?,
     override val canBeBatched: Boolean?,
-    override val ignorePartialData: Boolean?,
     private val useV3ExceptionHandling: Boolean?,
     private val builder: Builder,
 ) : ExecutionOptions, Closeable {
@@ -133,7 +131,6 @@ private constructor(
         .sendDocument(sendDocument)
         .enableAutoPersistedQueries(enableAutoPersistedQueries)
         .useV3ExceptionHandling(useV3ExceptionHandling)
-        .ignorePartialData(ignorePartialData)
         .apply {
           if (apolloRequest.httpMethod != null) {
             httpMethod(apolloRequest.httpMethod)
@@ -160,9 +157,6 @@ private constructor(
             // canBeBatched(apolloRequest.canBeBatched)
             addHttpHeader(ExecutionOptions.CAN_BE_BATCHED, apolloRequest.canBeBatched.toString())
           }
-          if (apolloRequest.ignorePartialData != null) {
-            ignorePartialData(apolloRequest.ignorePartialData)
-          }
           if (apolloRequest.useV3ExceptionHandling != null) {
             useV3ExceptionHandling(apolloRequest.useV3ExceptionHandling)
           }
@@ -171,28 +165,15 @@ private constructor(
 
     return DefaultInterceptorChain(interceptors + networkInterceptor, 0)
         .proceed(request)
-        .let { flow ->
+        .let {
           if (request.useV3ExceptionHandling == true) {
-            flow.onEach { response ->
+            it.onEach { response ->
               if (response.exception != null) {
                 throw response.exception!!
               }
             }
           } else {
-            flow
-          }
-        }
-        .let { flow ->
-          if (request.ignorePartialData == true) {
-            flow.map { response ->
-              if (response.data != null && response.hasErrors()) {
-                response.newBuilder().data(null).build()
-              } else {
-                response
-              }
-            }
-          } else {
-            flow
+            it
           }
         }
   }
@@ -285,13 +266,6 @@ private constructor(
       this.useV3ExceptionHandling = useV3ExceptionHandling
     }
 
-    override var ignorePartialData: Boolean? = null
-      private set
-
-    override fun ignorePartialData(ignorePartialData: Boolean?): Builder = apply {
-      this.ignorePartialData = ignorePartialData
-    }
-
     /**
      * The url of the GraphQL server used for HTTP
      *
@@ -597,7 +571,6 @@ private constructor(
           enableAutoPersistedQueries = enableAutoPersistedQueries,
           canBeBatched = canBeBatched,
           useV3ExceptionHandling = useV3ExceptionHandling,
-          ignorePartialData = ignorePartialData,
 
           // Keep a reference to the Builder so we can keep track of `httpEngine` and other properties that 
           // are important to rebuild `networkTransport` (and potentially others)
@@ -619,7 +592,6 @@ private constructor(
           .enableAutoPersistedQueries(enableAutoPersistedQueries)
           .canBeBatched(canBeBatched)
           .useV3ExceptionHandling(useV3ExceptionHandling)
-          .ignorePartialData(ignorePartialData)
       _networkTransport?.let { builder.networkTransport(it) }
       httpServerUrl?.let { builder.httpServerUrl(it) }
       httpEngine?.let { builder.httpEngine(it) }
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/interceptor/AutoPersistedQueryInterceptor.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/interceptor/AutoPersistedQueryInterceptor.kt
index 16e3e51151..fb1cb18774 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/interceptor/AutoPersistedQueryInterceptor.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/interceptor/AutoPersistedQueryInterceptor.kt
@@ -51,8 +51,7 @@ class AutoPersistedQueryInterceptor(
         }
         isPersistedQueryNotSupported(response.errors) -> {
           emit(
-              ApolloResponse.Builder(request.operation, request.requestUuid, null)
-                  .exception(AutoPersistedQueriesNotSupported())
+              ApolloResponse.Builder(request.operation, request.requestUuid, AutoPersistedQueriesNotSupported())
                   .build()
           )
           return@flow
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/MultipartReader.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/MultipartReader.kt
index 56af6243a0..4abb9bebea 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/MultipartReader.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/MultipartReader.kt
@@ -19,6 +19,7 @@ package com.apollographql.apollo3.internal
 import com.apollographql.apollo3.annotations.ApolloInternal
 import com.apollographql.apollo3.api.http.HttpHeader
 import com.apollographql.apollo3.exception.ApolloException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import okio.Buffer
 import okio.BufferedSource
 import okio.ByteString.Companion.encodeUtf8
@@ -110,7 +111,7 @@ class MultipartReader constructor(
       when (source.select(afterBoundaryOptions)) {
         0 -> {
           // "\r\n--<boundary>--": More parts, immediately followed by the closing delimiter.
-          if (partCount == 0) throw ApolloException("expected at least 1 part")
+          if (partCount == 0) throw DefaultApolloException("expected at least 1 part")
           noMoreParts = true
           return null
         }
@@ -123,8 +124,8 @@ class MultipartReader constructor(
 
         2 -> {
           // "--": No more parts.
-          if (whitespace) throw ApolloException("unexpected characters after boundary")
-          if (partCount == 0) throw ApolloException("expected at least 1 part")
+          if (whitespace) throw DefaultApolloException("unexpected characters after boundary")
+          if (partCount == 0) throw DefaultApolloException("expected at least 1 part")
           noMoreParts = true
           return null
         }
@@ -135,7 +136,7 @@ class MultipartReader constructor(
           continue@afterBoundaryLoop
         }
 
-        -1 -> throw ApolloException("unexpected characters after boundary")
+        -1 -> throw DefaultApolloException("unexpected characters after boundary")
       }
     }
 
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/multipart.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/multipart.kt
index 240091cea4..ef547fe843 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/multipart.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/multipart.kt
@@ -3,6 +3,7 @@ package com.apollographql.apollo3.internal
 import com.apollographql.apollo3.api.http.HttpResponse
 import com.apollographql.apollo3.api.http.valueOf
 import com.apollographql.apollo3.exception.ApolloException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.onCompletion
@@ -21,7 +22,7 @@ internal fun multipartBodyFlow(response: HttpResponse): Flow<BufferedSource> {
     multipartReader = MultipartReader(
         source = response.body!!,
         boundary = getBoundaryParameter(response.headers.valueOf("Content-Type"))
-            ?: throw ApolloException("Expected the Content-Type to have a boundary parameter")
+            ?: throw DefaultApolloException("Expected the Content-Type to have a boundary parameter")
     )
     while (true) {
       val part = multipartReader!!.nextPart() ?: break
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/BatchingHttpInterceptor.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/BatchingHttpInterceptor.kt
index 57868a040a..75be0accec 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/BatchingHttpInterceptor.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/BatchingHttpInterceptor.kt
@@ -17,6 +17,7 @@ import com.apollographql.apollo3.api.json.buildJsonByteString
 import com.apollographql.apollo3.api.json.writeArray
 import com.apollographql.apollo3.exception.ApolloException
 import com.apollographql.apollo3.exception.ApolloHttpException
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.internal.CloseableSingleThreadDispatcher
 import com.apollographql.apollo3.mpp.currentTimeMillis
 import kotlinx.coroutines.CompletableDeferred
@@ -177,19 +178,19 @@ class BatchingHttpInterceptor @JvmOverloads constructor(
             "HTTP error ${response.statusCode} while executing batched query"
         )
       }
-      val responseBody = response.body ?: throw ApolloException("null body when executing batched query")
+      val responseBody = response.body ?: throw DefaultApolloException("null body when executing batched query")
 
       // TODO: this is most likely going to transform BigNumbers into strings, not sure how much of an issue that is
       val list = AnyAdapter.fromJson(BufferedSourceJsonReader(responseBody), CustomScalarAdapters.Empty)
-      if (list !is List<*>) throw ApolloException("batched query response is not a list when executing batched query")
+      if (list !is List<*>) throw DefaultApolloException("batched query response is not a list when executing batched query")
 
       if (list.size != pending.size) {
-        throw ApolloException("batched query response count (${list.size}) does not match the requested queries (${pending.size})")
+        throw DefaultApolloException("batched query response count (${list.size}) does not match the requested queries (${pending.size})")
       }
 
       list.map {
         if (it == null) {
-          throw ApolloException("batched query response contains a null item")
+          throw DefaultApolloException("batched query response contains a null item")
         }
         (buildJsonByteString {
           AnyAdapter.toJson(this, CustomScalarAdapters.Empty, it)
@@ -198,7 +199,7 @@ class BatchingHttpInterceptor @JvmOverloads constructor(
     } catch (e: Exception) {
       exception = when (e) {
         is ApolloException -> e
-        else -> ApolloException("batched query failed with exception", e)
+        else -> DefaultApolloException("batched query failed with exception", e)
       }
       null
     }
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt
index 2187930fb8..e5d9e95e77 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt
@@ -110,8 +110,7 @@ private constructor(
           cause = throwable
       )
     }
-    return ApolloResponse.Builder(requestUuid = uuid4(), operation = operation, data = null)
-        .exception(apolloException)
+    return ApolloResponse.Builder(requestUuid = uuid4(), operation = operation, exception = apolloException)
         .isLast(true)
         .build()
   }
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt
index d1b5f80966..06cd29803d 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt
@@ -325,10 +325,8 @@ private constructor(
 
   private fun <D : Operation.Data> errorResponse(
       request: ApolloRequest<D>,
-      apolloException: ApolloException?,
-  ) =
-      ApolloResponse.Builder(requestUuid = request.requestUuid, operation = request.operation, data = null)
-          .exception(apolloException)
+      apolloException: ApolloException,
+  ) = ApolloResponse.Builder(requestUuid = request.requestUuid, operation = request.operation, exception = apolloException)
           .isLast(true)
           .build()
 
diff --git a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/RegisterOperations.kt b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/RegisterOperations.kt
index c7eba0a75a..52820ea8c7 100644
--- a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/RegisterOperations.kt
+++ b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/RegisterOperations.kt
@@ -269,7 +269,7 @@ object RegisterOperations {
       runBlocking { call.execute() }
     } catch (e: ApolloHttpException) {
       val body = e.body?.use { it.readUtf8() } ?: ""
-      throw ApolloException("Cannot push operations: (code: ${e.statusCode})\n$body", e)
+      throw Exception("Cannot push operations: (code: ${e.statusCode})\n$body", e)
     }
     check(!response.hasErrors()) {
       "Cannot push operations: ${response.errors!!.joinToString { it.message }}"
diff --git a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaDownloader.kt b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaDownloader.kt
index 096d22e279..488fa1b648 100644
--- a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaDownloader.kt
+++ b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaDownloader.kt
@@ -9,6 +9,7 @@ import com.apollographql.apollo3.ast.introspection.toGQLDocument
 import com.apollographql.apollo3.ast.introspection.toIntrospectionSchema
 import com.apollographql.apollo3.ast.introspection.writeTo
 import com.apollographql.apollo3.ast.parseAsGQLDocument
+import com.apollographql.apollo3.ast.toSchema
 import com.apollographql.apollo3.ast.toUtf8
 import com.apollographql.apollo3.ast.validateAsSchema
 import com.apollographql.apollo3.network.okHttpClient
@@ -69,7 +70,8 @@ object SchemaDownloader {
   ) {
     var introspectionSchemaJson: String? = null
     var introspectionSchema: IntrospectionSchema? = null
-    var gqlSchema: GQLDocument? = null
+    var sdlSchema: String? = null
+
     when {
       endpoint != null -> {
         var exception: Exception? = null
@@ -104,14 +106,14 @@ object SchemaDownloader {
           "Apollo: graph is required to download from the registry"
         }
 
-        gqlSchema = downloadRegistry(
+        sdlSchema = downloadRegistry(
             graph = graph2,
             key = key,
             variant = graphVariant,
             endpoint = registryUrl,
             headers = headers,
             insecure = insecure,
-        ).let { Buffer().writeUtf8(it) }.parseAsGQLDocument().getOrThrow()
+        )
       }
     }
 
@@ -119,16 +121,26 @@ object SchemaDownloader {
 
     if (schema.extension.lowercase() == "json") {
       if (introspectionSchema == null) {
-        introspectionSchema = gqlSchema!!.validateAsSchema().getOrThrow().toIntrospectionSchema()
-        introspectionSchema.writeTo(schema)
+        check(sdlSchema != null)
+        // Convert from SDL to JSON
+        Buffer().writeUtf8(sdlSchema)
+            .toSchema()
+            .toIntrospectionSchema()
+            .writeTo(schema)
       } else {
-        schema.writeText(introspectionSchemaJson!!)
+        check(introspectionSchemaJson != null)
+        // Copy Json verbatim
+        schema.writeText(introspectionSchemaJson)
       }
     } else {
-      if (gqlSchema == null) {
-        gqlSchema = introspectionSchema!!.toGQLDocument()
+      if (sdlSchema == null) {
+        check(introspectionSchema != null)
+        // Convert from JSON to SDL
+        schema.writeText(introspectionSchema.toGQLDocument().toUtf8(indent = "  "))
+      } else {
+        // Copy SDL verbatim
+        schema.writeText(sdlSchema)
       }
-      schema.writeText(gqlSchema.toUtf8(indent = "  "))
     }
   }
 
@@ -164,8 +176,7 @@ object SchemaDownloader {
         .build()
     val response = runBlocking {
       apolloClient.query(DownloadSchemaQuery(graphID = graph, variant = variant))
-          .httpHeaders(headers.map { HttpHeader(it.key, it.value) })
-          .addHttpHeader("x-api-key", key)
+          .httpHeaders(headers.map { HttpHeader(it.key, it.value) } + HttpHeader("x-api-key", key))
           .execute()
     }
     check(!response.hasErrors()) {
diff --git a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaUploader.kt b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaUploader.kt
index f6e437d1f9..a36cfc3e50 100644
--- a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaUploader.kt
+++ b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo3/tooling/SchemaUploader.kt
@@ -76,7 +76,7 @@ object SchemaUploader {
       runBlocking { call.execute() }
     } catch (e: ApolloHttpException) {
       val body = e.body?.use { it.readUtf8() } ?: ""
-      throw ApolloException("Cannot upload schema: (code: ${e.statusCode})\n$body", e)
+      throw Exception("Cannot upload schema: (code: ${e.statusCode})\n$body", e)
     }
     check(!response.hasErrors()) {
       "Cannot upload schema: ${response.errors!!.joinToString { it.message }}"
@@ -112,7 +112,7 @@ object SchemaUploader {
       runBlocking { call.execute() }
     } catch (e: ApolloHttpException) {
       val body = e.body?.use { it.readUtf8() } ?: ""
-      throw ApolloException("Cannot upload schema: (code: ${e.statusCode})\n$body", e)
+      throw Exception("Cannot upload schema: (code: ${e.statusCode})\n$body", e)
     }
     check(!response.hasErrors()) {
       "Cannot upload schema: ${response.errors!!.joinToString { it.message }}"


Test patch:
diff --git a/libraries/apollo-testing-support/src/commonMain/kotlin/com/apollographql/apollo3/testing/TestNetworkTransport.kt b/libraries/apollo-testing-support/src/commonMain/kotlin/com/apollographql/apollo3/testing/TestNetworkTransport.kt
index a1b6498cb3..91e301c7a3 100644
--- a/libraries/apollo-testing-support/src/commonMain/kotlin/com/apollographql/apollo3/testing/TestNetworkTransport.kt
+++ b/libraries/apollo-testing-support/src/commonMain/kotlin/com/apollographql/apollo3/testing/TestNetworkTransport.kt
@@ -35,9 +35,7 @@ class QueueTestNetworkTransport : NetworkTransport {
 
       val apolloResponse = when (response) {
         is TestResponse.NetworkError -> {
-          ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid, data = null)
-              .exception(ApolloNetworkException("Network error queued in QueueTestNetworkTransport"))
-              .build()
+          ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid, exception = ApolloNetworkException("Network error queued in QueueTestNetworkTransport")).build()
         }
 
         is TestResponse.Response -> {
@@ -75,9 +73,7 @@ class MapTestNetworkTransport : NetworkTransport {
         ?: error("No response registered for operation ${request.operation}")
     val apolloResponse = when (response) {
       is TestResponse.NetworkError -> {
-        ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid, data = null)
-            .exception(ApolloNetworkException("Network error registered in MapTestNetworkTransport"))
-            .build()
+        ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid, exception = ApolloNetworkException("Network error registered in MapTestNetworkTransport")).build()
       }
 
       is TestResponse.Response -> {
@@ -117,9 +113,10 @@ fun <D : Operation.Data> ApolloClient.enqueueTestResponse(
     ApolloResponse.Builder(
         operation = operation,
         requestUuid = uuid4(),
-        data = data
+        data = data,
+        errors = errors,
+        extensions = null
     )
-        .errors(errors)
         .build()
 )
 
@@ -146,9 +143,10 @@ fun <D : Operation.Data> ApolloClient.registerTestResponse(
     ApolloResponse.Builder(
         operation = operation,
         requestUuid = uuid4(),
-        data = data
+        data = data,
+        errors = errors,
+        extensions = null
     )
-        .errors(errors)
         .build()
 )
 
diff --git a/tests/coroutines-mt/src/appleTest/kotlin/macos/app/MainTest.kt b/tests/coroutines-mt/src/appleTest/kotlin/macos/app/MainTest.kt
index fb44436fa6..35d20fd9d2 100644
--- a/tests/coroutines-mt/src/appleTest/kotlin/macos/app/MainTest.kt
+++ b/tests/coroutines-mt/src/appleTest/kotlin/macos/app/MainTest.kt
@@ -28,7 +28,7 @@ class MainTest {
           .build()
           .query(GetRandomQuery())
           .execute()
-      check(response.dataAssertNoErrors.random == 42)
+      check(response.dataOrThrow().random == 42)
     }
   }
 
@@ -39,7 +39,7 @@ class MainTest {
     val client = ApolloClient.Builder().serverUrl(server.url()).normalizedCache(MemoryCacheFactory()).build()
     withContext(Dispatchers.Default) {
       val response = client.query(GetRandomQuery()).execute()
-      check(response.dataAssertNoErrors.random == 42)
+      check(response.dataOrThrow().random == 42)
     }
   }
 }
diff --git a/tests/defer/src/commonTest/kotlin/test/DeferNormalizedCacheTest.kt b/tests/defer/src/commonTest/kotlin/test/DeferNormalizedCacheTest.kt
index 43592ace95..3cf7b825a9 100644
--- a/tests/defer/src/commonTest/kotlin/test/DeferNormalizedCacheTest.kt
+++ b/tests/defer/src/commonTest/kotlin/test/DeferNormalizedCacheTest.kt
@@ -73,7 +73,7 @@ class DeferNormalizedCacheTest {
     mockServer.takeRequest()
 
     // Cache is not empty, so this doesn't go to the server
-    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataAssertNoErrors
+    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataOrThrow()
     assertFails { mockServer.takeRequest() }
 
     // We get the last/fully formed data
@@ -101,7 +101,7 @@ class DeferNormalizedCacheTest {
 
     // Cache is not empty, but NetworkOnly still goes to the server
     mockServer.enqueueMultipart(jsonList)
-    val networkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val networkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     val networkExpected = listOf(
@@ -135,7 +135,7 @@ class DeferNormalizedCacheTest {
     // Cache is empty, so this goes to the server
     val responses = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList()
     assertTrue(responses[0].exception is CacheMissException)
-    val networkActual = responses.drop(1).map { it.dataAssertNoErrors }
+    val networkActual = responses.drop(1).map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     val networkExpected = listOf(
@@ -155,7 +155,7 @@ class DeferNormalizedCacheTest {
     assertEquals(networkExpected, networkActual)
 
     // Cache is not empty, so this doesn't go to the server
-    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataAssertNoErrors
+    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataOrThrow()
     assertFails { mockServer.takeRequest() }
 
     // We get the last/fully formed data
@@ -175,7 +175,7 @@ class DeferNormalizedCacheTest {
     mockServer.enqueueMultipart(jsonList)
 
     // Cache is empty, so this goes to the server
-    val networkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val networkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     val networkExpected = listOf(
@@ -196,7 +196,7 @@ class DeferNormalizedCacheTest {
 
     mockServer.enqueue(statusCode = 500)
     // Network will fail, so we get the cached version
-    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataAssertNoErrors
+    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).execute().dataOrThrow()
 
     // We get the last/fully formed data
     val cacheExpected = networkExpected.last()
@@ -217,7 +217,7 @@ class DeferNormalizedCacheTest {
     // Cache is empty
     val responses = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList()
     assertTrue(responses[0].exception is CacheMissException)
-    val networkActual = responses.drop(1).map { it.dataAssertNoErrors }
+    val networkActual = responses.drop(1).map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     val networkExpected = listOf(
@@ -244,7 +244,7 @@ class DeferNormalizedCacheTest {
     mockServer.enqueueMultipart(jsonList2)
 
     // Cache is not empty
-    val cacheAndNetworkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val cacheAndNetworkActual = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     // We get a combination of the last/fully formed data from the cache + the new network data
@@ -329,7 +329,7 @@ class DeferNormalizedCacheTest {
     mockServer.enqueue(statusCode = 500)
     // Because of the error the cache is missing some fields, so we get a cache miss, and fallback to the network (which also fails)
     val exception = assertFailsWith<CacheMissException> {
-      apolloClient.query(WithFragmentSpreadsQuery()).execute().dataAssertNoErrors
+      apolloClient.query(WithFragmentSpreadsQuery()).execute().dataOrThrow()
     }
     assertIs<ApolloHttpException>(exception.suppressedExceptions.first())
     assertEquals("Object 'computers.0.screen' has no field named 'isColor'", exception.message)
@@ -372,8 +372,7 @@ class DeferNormalizedCacheTest {
                     emit(networkResponse as ApolloResponse<D>)
                   }
                   delay(10)
-                  emit(ApolloResponse.Builder(requestUuid = uuid, operation = query, data = null)
-                      .exception(ApolloNetworkException("Network error"))
+                  emit(ApolloResponse.Builder(requestUuid = uuid, operation = query, exception = ApolloNetworkException("Network error"))
                       .isLast(true)
                       .build() as ApolloResponse<D>)
                 }
@@ -406,7 +405,7 @@ class DeferNormalizedCacheTest {
         """{"incremental": [{"data":{"isColor":false},"path":["computers",0,"screen"],"label":"a"}],"hasNext":false}""",
     )
     mockServer.enqueueMultipart(jsonList)
-    val networkActual = apolloClient.mutation(WithFragmentSpreadsMutation()).toFlow().toList().map { it.dataAssertNoErrors }
+    val networkActual = apolloClient.mutation(WithFragmentSpreadsMutation()).toFlow().toList().map { it.dataOrThrow() }
     mockServer.takeRequest()
 
     val networkExpected = listOf(
@@ -426,7 +425,7 @@ class DeferNormalizedCacheTest {
     assertEquals(networkExpected, networkActual)
 
     // Now cache is not empty
-    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).fetchPolicy(FetchPolicy.CacheOnly).execute().dataAssertNoErrors
+    val cacheActual = apolloClient.query(WithFragmentSpreadsQuery()).fetchPolicy(FetchPolicy.CacheOnly).execute().dataOrThrow()
 
     // We get the last/fully formed data
     val cacheExpected = WithFragmentSpreadsQuery.Data(
diff --git a/tests/defer/src/commonTest/kotlin/test/DeferSubscriptionsTest.kt b/tests/defer/src/commonTest/kotlin/test/DeferSubscriptionsTest.kt
index e00eaf9a01..fa5e3dc1af 100644
--- a/tests/defer/src/commonTest/kotlin/test/DeferSubscriptionsTest.kt
+++ b/tests/defer/src/commonTest/kotlin/test/DeferSubscriptionsTest.kt
@@ -49,7 +49,7 @@ class DeferSubscriptionsTest {
         WithInlineFragmentsSubscription.Data(WithInlineFragmentsSubscription.Count("Counter", 3, WithInlineFragmentsSubscription.OnCounter(6))),
     )
 
-    val actualDataList = apolloClient.subscription(WithInlineFragmentsSubscription()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.subscription(WithInlineFragmentsSubscription()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -70,7 +70,7 @@ class DeferSubscriptionsTest {
         WithFragmentSpreadsSubscription.Data(WithFragmentSpreadsSubscription.Count("Counter", 3, CounterFields(6))),
     )
 
-    val actualDataList = apolloClient.subscription(WithFragmentSpreadsSubscription()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.subscription(WithFragmentSpreadsSubscription()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
diff --git a/tests/defer/src/commonTest/kotlin/test/DeferTest.kt b/tests/defer/src/commonTest/kotlin/test/DeferTest.kt
index ba9b353ec6..a169d0d4f2 100644
--- a/tests/defer/src/commonTest/kotlin/test/DeferTest.kt
+++ b/tests/defer/src/commonTest/kotlin/test/DeferTest.kt
@@ -93,7 +93,7 @@ class DeferTest {
     )
 
     mockServer.enqueueMultipart(jsonList)
-    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -151,7 +151,7 @@ class DeferTest {
     )
 
     mockServer.enqueueMultipart(jsonList)
-    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -309,11 +309,11 @@ class DeferTest {
     )
 
     mockServer.enqueueMultipart(jsonWithEmptyPayload)
-    var actualDataList = apolloClient.query(SimpleDeferQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    var actualDataList = apolloClient.query(SimpleDeferQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
 
     mockServer.enqueueMultipart(jsonWithoutEmptyPayload)
-    actualDataList = apolloClient.query(SimpleDeferQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    actualDataList = apolloClient.query(SimpleDeferQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 }
diff --git a/tests/defer/src/commonTest/kotlin/test/DeferWithRouterTest.kt b/tests/defer/src/commonTest/kotlin/test/DeferWithRouterTest.kt
index fcdd21b025..53135bef38 100644
--- a/tests/defer/src/commonTest/kotlin/test/DeferWithRouterTest.kt
+++ b/tests/defer/src/commonTest/kotlin/test/DeferWithRouterTest.kt
@@ -81,7 +81,7 @@ class DeferWithRouterTest {
         ),
     )
 
-    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -117,7 +117,7 @@ class DeferWithRouterTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -154,7 +154,7 @@ class DeferWithRouterTest {
         ),
     )
 
-    val actualDataList = apolloClient.mutation(WithFragmentSpreadsMutation()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.mutation(WithFragmentSpreadsMutation()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -170,7 +170,7 @@ class DeferWithRouterTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(CanDisableDeferUsingIfArgumentQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(CanDisableDeferUsingIfArgumentQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -193,7 +193,7 @@ class DeferWithRouterTest {
             )
         )
     )
-    val actualDataList = apolloClient.query(DoesNotDisableDeferWithNullIfArgumentQuery(Optional.Absent)).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(DoesNotDisableDeferWithNullIfArgumentQuery(Optional.Absent)).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -217,7 +217,7 @@ class DeferWithRouterTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(CanDeferFragmentsOnTheTopLevelQueryFieldQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(CanDeferFragmentsOnTheTopLevelQueryFieldQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -238,7 +238,7 @@ class DeferWithRouterTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(CanDeferAFragmentThatIsAlsoNotDeferredDeferredFragmentIsFirstQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(CanDeferAFragmentThatIsAlsoNotDeferredDeferredFragmentIsFirstQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -259,7 +259,7 @@ class DeferWithRouterTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(CanDeferAFragmentThatIsAlsoNotDeferredNotDeferredFragmentIsFirstQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(CanDeferAFragmentThatIsAlsoNotDeferredNotDeferredFragmentIsFirstQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
diff --git a/tests/defer/src/jsTest/kotlin/test/DeferWithHelixTest.kt b/tests/defer/src/jsTest/kotlin/test/DeferWithHelixTest.kt
index 9b8fe4c711..ac7b07bc8b 100644
--- a/tests/defer/src/jsTest/kotlin/test/DeferWithHelixTest.kt
+++ b/tests/defer/src/jsTest/kotlin/test/DeferWithHelixTest.kt
@@ -189,7 +189,7 @@ class DeferWithHelixTest {
         ),
     )
 
-    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithFragmentSpreadsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -237,7 +237,7 @@ class DeferWithHelixTest {
             )
         ),
     )
-    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.query(WithInlineFragmentsQuery()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -258,7 +258,7 @@ class DeferWithHelixTest {
         WithInlineFragmentsSubscription.Data(WithInlineFragmentsSubscription.Count("Counter", 3, WithInlineFragmentsSubscription.OnCounter(6))),
     )
 
-    val actualDataList = apolloClient.subscription(WithInlineFragmentsSubscription()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.subscription(WithInlineFragmentsSubscription()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 
@@ -279,7 +279,7 @@ class DeferWithHelixTest {
         WithFragmentSpreadsSubscription.Data(WithFragmentSpreadsSubscription.Count("Counter", 3, CounterFields(6))),
     )
 
-    val actualDataList = apolloClient.subscription(WithFragmentSpreadsSubscription()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.subscription(WithFragmentSpreadsSubscription()).toFlow().toList().map { it.dataOrThrow() }
     assertEquals(expectedDataList, actualDataList)
   }
 }
diff --git a/tests/defer/src/jvmTest/kotlin/test/DeferJvmTest.kt b/tests/defer/src/jvmTest/kotlin/test/DeferJvmTest.kt
index b77c2a6e24..13d16b8a67 100644
--- a/tests/defer/src/jvmTest/kotlin/test/DeferJvmTest.kt
+++ b/tests/defer/src/jvmTest/kotlin/test/DeferJvmTest.kt
@@ -81,7 +81,7 @@ class DeferJvmTest {
     job.cancel()
 
     // Also check that caching worked
-    val actual = apolloClient.query(WithFragmentSpreadsQuery()).httpFetchPolicy(HttpFetchPolicy.CacheOnly).toFlow().last().dataAssertNoErrors
+    val actual = apolloClient.query(WithFragmentSpreadsQuery()).httpFetchPolicy(HttpFetchPolicy.CacheOnly).toFlow().last().dataOrThrow()
     val expected = WithFragmentSpreadsQuery.Data(
         listOf(
             WithFragmentSpreadsQuery.Computer("Computer", "Computer1", ComputerFields("386", 1993,
diff --git a/tests/escaping/src/test/kotlin/test/EscapingTest.kt b/tests/escaping/src/test/kotlin/test/EscapingTest.kt
index 8f89a64a0e..91d81399ca 100644
--- a/tests/escaping/src/test/kotlin/test/EscapingTest.kt
+++ b/tests/escaping/src/test/kotlin/test/EscapingTest.kt
@@ -17,7 +17,7 @@ class EscapingTest {
             ),
         ))
         .execute()
-    val `while`: WhileQuery.While? = response.dataAssertNoErrors.`while`
+    val `while`: WhileQuery.While? = response.dataOrThrow().`while`
 
     @Suppress("UNUSED_VARIABLE")
     val `if`: String? = `while`?.`if`
diff --git a/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt b/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt
index 2b031a0d17..04b0e4f474 100644
--- a/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt
+++ b/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt
@@ -42,7 +42,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals("meeoooowwwww", response.dataAssertNoErrors.animal!!.onCat!!.meow)
+    assertEquals("meeoooowwwww", response.dataOrThrow().animal!!.onCat!!.meow)
   }
 
   @Test
@@ -57,7 +57,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals(null, response.dataAssertNoErrors.animal!!.onCat)
+    assertEquals(null, response.dataOrThrow().animal!!.onCat)
   }
 
   @Test
@@ -72,7 +72,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals("meeoooowwwww", response.dataAssertNoErrors.animal!!.onCat!!.meow)
+    assertEquals("meeoooowwwww", response.dataOrThrow().animal!!.onCat!!.meow)
   }
 
   @Test
@@ -87,7 +87,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals(null, response.dataAssertNoErrors.animal!!.onCat)
+    assertEquals(null, response.dataOrThrow().animal!!.onCat)
   }
 
   @Test
@@ -102,7 +102,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals(null, response.dataAssertNoErrors.animal!!.dogFragment)
+    assertEquals(null, response.dataOrThrow().animal!!.dogFragment)
   }
 
   @Test
@@ -117,7 +117,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals("ouaf", response.dataAssertNoErrors.animal!!.dogFragment!!.barf)
+    assertEquals("ouaf", response.dataOrThrow().animal!!.dogFragment!!.barf)
   }
 
   @Test
@@ -132,7 +132,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals(null, response.dataAssertNoErrors.animal!!.dogFragment)
+    assertEquals(null, response.dataOrThrow().animal!!.dogFragment)
   }
 
   @Test
@@ -147,7 +147,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertEquals("ouaf", response.dataAssertNoErrors.animal!!.dogFragment!!.barf)
+    assertEquals("ouaf", response.dataOrThrow().animal!!.dogFragment!!.barf)
   }
 
   @Test
@@ -175,7 +175,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertNull(response.dataAssertNoErrors.animal!!.species)
+    assertNull(response.dataOrThrow().animal!!.species)
   }
 
   @Test
@@ -190,7 +190,7 @@ class IncludeTest {
 
     val response = operation.parseData(data)
 
-    assertNotNull(response.dataAssertNoErrors.animal!!.dogFragment)
+    assertNotNull(response.dataOrThrow().animal!!.dogFragment)
   }
 
   @Test
diff --git a/tests/integration-tests/src/commonTest/kotlin/test/CacheFlagsTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/CacheFlagsTest.kt
index 8ced5111ca..1bfdf258c3 100644
--- a/tests/integration-tests/src/commonTest/kotlin/test/CacheFlagsTest.kt
+++ b/tests/integration-tests/src/commonTest/kotlin/test/CacheFlagsTest.kt
@@ -100,7 +100,7 @@ class CacheFlagsTest {
     val query = HeroNameQuery()
     apolloClient.enqueueTestResponse(query, partialResponseData, partialResponseErrors)
 
-    // this should not store the response
+    // this should store the response
     apolloClient.query(query).storePartialResponses(true).execute()
 
     val response = apolloClient.query(query).fetchPolicy(FetchPolicy.CacheOnly).execute()
diff --git a/tests/integration-tests/src/commonTest/kotlin/test/ErrorsTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/ErrorsTest.kt
deleted file mode 100644
index d5ee789e68..0000000000
--- a/tests/integration-tests/src/commonTest/kotlin/test/ErrorsTest.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package test
-
-import com.apollographql.apollo3.ApolloClient
-import com.apollographql.apollo3.integration.normalizer.HeroNameQuery
-import com.apollographql.apollo3.mockserver.MockServer
-import com.apollographql.apollo3.mockserver.enqueue
-import com.apollographql.apollo3.testing.internal.runTest
-import kotlin.test.Test
-import kotlin.test.assertNull
-
-class ErrorsTest {
-  private lateinit var mockServer: MockServer
-
-  private fun setUp() {
-    mockServer = MockServer()
-  }
-
-  private suspend fun tearDown() {
-    mockServer.stop()
-  }
-
-  @Test
-  fun ignorePartialDataOnClient() = runTest(before = { setUp() }, after = { tearDown() }) {
-    val apolloClient = ApolloClient.Builder()
-        .serverUrl(mockServer.url())
-        .ignorePartialData(true)
-        .build()
-    mockServer.enqueue("""
-      {
-        "data": {
-          "hero": {
-            "name": "R2-D2"
-          }
-        },
-        "errors": [
-          {
-            "message": "Something went wrong"
-          }
-        ]
-      }
-    """.trimIndent())
-
-    val response = apolloClient.query(HeroNameQuery()).execute()
-    assertNull(response.data)
-  }
-
-  @Test
-  fun ignorePartialDataOnCall() = runTest(before = { setUp() }, after = { tearDown() }) {
-    val apolloClient = ApolloClient.Builder()
-        .serverUrl(mockServer.url())
-        .build()
-    mockServer.enqueue("""
-      {
-        "data": {
-          "hero": {
-            "name": "R2-D2"
-          }
-        },
-        "errors": [
-          {
-            "message": "Something went wrong"
-          }
-        ]
-      }
-    """.trimIndent())
-
-    val response = apolloClient.query(HeroNameQuery()).ignorePartialData(true).execute()
-    assertNull(response.data)
-  }
-
-}
diff --git a/tests/integration-tests/src/commonTest/kotlin/test/ScalarAdapterTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/ScalarAdapterTest.kt
index 3ebdadc686..823b313857 100644
--- a/tests/integration-tests/src/commonTest/kotlin/test/ScalarAdapterTest.kt
+++ b/tests/integration-tests/src/commonTest/kotlin/test/ScalarAdapterTest.kt
@@ -54,6 +54,6 @@ class ScalarAdapterTest {
     val request = mockServer.takeRequest()
     assertTrue(request.body.utf8().contains(""""variables":{"date":"2001-6-23"}"""))
 
-    assertEquals(MyDate(1978, 4, 27), response.dataAssertNoErrors.launchByDate?.date)
+    assertEquals(MyDate(1978, 4, 27), response.dataOrThrow().launchByDate?.date)
   }
 }
diff --git a/tests/java-client/src/test/java/test/ApolloWsTest.java b/tests/java-client/src/test/java/test/ApolloWsTest.java
index 09540fa7df..ec6a97d212 100644
--- a/tests/java-client/src/test/java/test/ApolloWsTest.java
+++ b/tests/java-client/src/test/java/test/ApolloWsTest.java
@@ -59,7 +59,7 @@ public class ApolloWsTest {
     ApolloDisposable disposable = apolloClient.subscription(new CountSubscription(5, 100)).enqueue(new ApolloCallback<CountSubscription.Data>() {
       @Override
       public void onResponse(@NotNull ApolloResponse<CountSubscription.Data> response) {
-        actual.add(response.dataAssertNoErrors().count);
+        actual.add(response.dataOrThrow().count);
         latch.countDown();
       }
     });
@@ -77,7 +77,7 @@ public class ApolloWsTest {
   @Test
   public void simpleWithRx() {
     Rx3Apollo.flowable(apolloClient.subscription(new CountSubscription(5, 100)), BackpressureStrategy.BUFFER)
-        .map(response -> response.dataAssertNoErrors().count)
+        .map(response -> response.dataOrThrow().count)
         .test()
         .awaitDone(1, TimeUnit.SECONDS)
         .assertValueCount(5)
@@ -92,7 +92,7 @@ public class ApolloWsTest {
     apolloClient.subscription(new CountSubscription(4, 2000)).enqueue(new ApolloCallback<CountSubscription.Data>() {
       @Override
       public void onResponse(@NotNull ApolloResponse<CountSubscription.Data> response) {
-        Integer count = response.dataAssertNoErrors().count;
+        Integer count = response.dataOrThrow().count;
         items.add(count * 2);
         if (count == 0) {
           sleep(500);
@@ -100,7 +100,7 @@ public class ApolloWsTest {
           apolloClient.subscription(new CountSubscription(4, 2000)).enqueue(new ApolloCallback<CountSubscription.Data>() {
             @Override
             public void onResponse(@NotNull ApolloResponse<CountSubscription.Data> response) {
-              items.add(response.dataAssertNoErrors().count * 2 + 1);
+              items.add(response.dataOrThrow().count * 2 + 1);
             }
           }).addListener(latch::countDown);
         }
@@ -174,8 +174,8 @@ public class ApolloWsTest {
     disposable[0] = apolloClient.subscription(new CountSubscription(50, 10)).enqueue(new ApolloCallback<CountSubscription.Data>() {
       @Override
       public void onResponse(@NotNull ApolloResponse<CountSubscription.Data> response) {
-        items.add(response.dataAssertNoErrors().count);
-        if (response.dataAssertNoErrors().count == 5) {
+        items.add(response.dataOrThrow().count);
+        if (response.dataOrThrow().count == 5) {
           disposable[0].dispose();
           latch.countDown();
         }
@@ -206,8 +206,8 @@ public class ApolloWsTest {
           failure[0] = response.exception;
           latch.countDown();
         } else {
-          items.add(response.dataAssertNoErrors().count);
-          if (response.dataAssertNoErrors().count == 5) {
+          items.add(response.dataOrThrow().count);
+          if (response.dataOrThrow().count == 5) {
             // Provoke a network error by closing the websocket
             apolloClient.query(new CloseSocketQuery()).enqueue(new ApolloCallback<CloseSocketQuery.Data>() {
               @Override
@@ -254,11 +254,11 @@ public class ApolloWsTest {
           latch.countDown();
         } else {
           if (hasReopenOccurred.get()) {
-            itemsAfterReopen.add(response.dataAssertNoErrors().count);
+            itemsAfterReopen.add(response.dataOrThrow().count);
           } else {
-            itemsBeforeReopen.add(response.dataAssertNoErrors().count);
+            itemsBeforeReopen.add(response.dataOrThrow().count);
           }
-          if (response.dataAssertNoErrors().count == 5) {
+          if (response.dataOrThrow().count == 5) {
             // Provoke a network error by closing the websocket
             apolloClient.query(new CloseSocketQuery()).enqueue(new ApolloCallback<CloseSocketQuery.Data>() {
               @Override
@@ -313,8 +313,8 @@ public class ApolloWsTest {
           failure[0] = response.exception;
           latch.countDown();
         } else {
-          itemsBeforeReopen.add(response.dataAssertNoErrors().count);
-          if (response.dataAssertNoErrors().count == 5) {
+          itemsBeforeReopen.add(response.dataOrThrow().count);
+          if (response.dataOrThrow().count == 5) {
             // Provoke a network error by stopping the whole server
             sampleServer2.close();
           }
diff --git a/tests/java-client/src/test/java/test/BatchingTest.java b/tests/java-client/src/test/java/test/BatchingTest.java
index a2d1561727..04ea856f2a 100644
--- a/tests/java-client/src/test/java/test/BatchingTest.java
+++ b/tests/java-client/src/test/java/test/BatchingTest.java
@@ -73,7 +73,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunchQuery()).enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -84,7 +84,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunch2Query()).enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -123,7 +123,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunchQuery()).enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -134,7 +134,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunch2Query()).enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -166,7 +166,7 @@ public class BatchingTest {
         .enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
           @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
             synchronized (items) {
-              items.add(response.dataAssertNoErrors().launch.id);
+              items.add(response.dataOrThrow().launch.id);
             }
             latch.countDown();
           }
@@ -177,7 +177,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunch2Query()).enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -210,7 +210,7 @@ public class BatchingTest {
         .enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
           @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
             synchronized (items) {
-              items.add(response.dataAssertNoErrors().launch.id);
+              items.add(response.dataOrThrow().launch.id);
             }
             latch.countDown();
           }
@@ -224,7 +224,7 @@ public class BatchingTest {
         .enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
           @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
             synchronized (items) {
-              items.add(response.dataAssertNoErrors().launch.id);
+              items.add(response.dataOrThrow().launch.id);
             }
             latch.countDown();
           }
@@ -266,7 +266,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunchQuery()).enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -277,7 +277,7 @@ public class BatchingTest {
     apolloClient.query(new GetLaunch2Query()).enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
       @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
         synchronized (items) {
-          items.add(response.dataAssertNoErrors().launch.id);
+          items.add(response.dataOrThrow().launch.id);
         }
         latch.countDown();
       }
@@ -312,7 +312,7 @@ public class BatchingTest {
         .enqueue(new ApolloCallback<GetLaunchQuery.Data>() {
           @Override public void onResponse(@NotNull ApolloResponse<GetLaunchQuery.Data> response) {
             synchronized (items) {
-              items.add(response.dataAssertNoErrors().launch.id);
+              items.add(response.dataOrThrow().launch.id);
             }
             latch.countDown();
           }
@@ -328,7 +328,7 @@ public class BatchingTest {
         .enqueue(new ApolloCallback<GetLaunch2Query.Data>() {
           @Override public void onResponse(@NotNull ApolloResponse<GetLaunch2Query.Data> response) {
             synchronized (items) {
-              items.add(response.dataAssertNoErrors().launch.id);
+              items.add(response.dataOrThrow().launch.id);
             }
             latch.countDown();
           }
diff --git a/tests/java-client/src/test/java/test/ClientTest.java b/tests/java-client/src/test/java/test/ClientTest.java
index c1ddaee8f1..3b01ea2466 100644
--- a/tests/java-client/src/test/java/test/ClientTest.java
+++ b/tests/java-client/src/test/java/test/ClientTest.java
@@ -6,17 +6,14 @@ import com.apollographql.apollo3.api.Operation;
 import com.apollographql.apollo3.mockserver.MockRequest;
 import com.apollographql.apollo3.mockserver.MockResponse;
 import com.apollographql.apollo3.mockserver.MockServer;
-import com.apollographql.apollo3.runtime.java.ApolloCall;
 import com.apollographql.apollo3.runtime.java.ApolloCallback;
 import com.apollographql.apollo3.runtime.java.ApolloClient;
 import com.apollographql.apollo3.runtime.java.ApolloDisposable;
 import com.apollographql.apollo3.runtime.java.interceptor.ApolloInterceptor;
 import com.apollographql.apollo3.runtime.java.interceptor.ApolloInterceptorChain;
 import com.apollographql.apollo3.runtime.java.network.http.HttpInterceptor;
-import com.apollographql.apollo3.rx3.java.Rx3Apollo;
 import com.google.common.truth.Truth;
 import io.reactivex.rxjava3.annotations.NonNull;
-import io.reactivex.rxjava3.core.BackpressureStrategy;
 import javatest.CreateCatMutation;
 import javatest.GetRandomQuery;
 import javatest.LocationQuery;
@@ -62,11 +59,11 @@ public class ClientTest {
   public void simple() {
     mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"random\": 42}}").build());
     @NonNull ApolloResponse<GetRandomQuery.Data> queryResponse = blockingQuery(apolloClient, GetRandomQuery.builder().build());
-    Truth.assertThat(queryResponse.dataAssertNoErrors().random).isEqualTo(42);
+    Truth.assertThat(queryResponse.dataOrThrow().random).isEqualTo(42);
 
     mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"createAnimal\": {\"__typename\": \"Cat\", \"species\": \"cat\", \"habitat\": {\"temperature\": 10.5}}}}").build());
     @NonNull ApolloResponse<CreateCatMutation.Data> mutationResponse = blockingMutation(apolloClient, CreateCatMutation.builder().build());
-    Truth.assertThat(mutationResponse.dataAssertNoErrors().createAnimal.catFragment.species).isEqualTo("cat");
+    Truth.assertThat(mutationResponse.dataOrThrow().createAnimal.catFragment.species).isEqualTo("cat");
   }
 
   @Test
@@ -147,8 +144,8 @@ public class ClientTest {
 
     mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"location\": {\"latitude\": 10.5, \"longitude\": 20.5}}}").build());
     ApolloResponse<LocationQuery.Data> queryResponse = blockingQuery(apolloClient, LocationQuery.builder().build());
-    Truth.assertThat(queryResponse.dataAssertNoErrors().location.latitude).isEqualTo(10.5);
-    Truth.assertThat(queryResponse.dataAssertNoErrors().location.longitude).isEqualTo(20.5);
+    Truth.assertThat(queryResponse.dataOrThrow().location.latitude).isEqualTo(10.5);
+    Truth.assertThat(queryResponse.dataOrThrow().location.longitude).isEqualTo(20.5);
   }
 
   @Test
@@ -179,22 +176,4 @@ public class ClientTest {
      */
     Truth.assertThat(received[0]).isEqualTo(null);
   }
-
-  @Test
-  public void ignorePartialDataOnClient() {
-    apolloClient = new ApolloClient.Builder().serverUrl(mockServerUrl).ignorePartialData(true).build();
-    mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"random\": 42}, \"errors\":  [{\"message\": \"Something went wrong\"}]}").build());
-    @NonNull ApolloResponse<GetRandomQuery.Data> queryResponse = blockingQuery(apolloClient, GetRandomQuery.builder().build());
-    Truth.assertThat(queryResponse.data).isNull();
-  }
-
-  @Test
-  public void ignorePartialDataOnCall() {
-    mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"random\": 42}, \"errors\":  [{\"message\": \"Something went wrong\"}]}").build());
-    GetRandomQuery query = GetRandomQuery.builder().build();
-    ApolloCall<GetRandomQuery.Data> call = apolloClient.query(query).ignorePartialData(true);
-    @NonNull ApolloResponse<GetRandomQuery.Data> queryResponse = Rx3Apollo.single(call, BackpressureStrategy.BUFFER).blockingGet();
-    Truth.assertThat(queryResponse.data).isNull();
-  }
-
 }
diff --git a/tests/java-client/src/test/java/test/GraphQLWsTest.java b/tests/java-client/src/test/java/test/GraphQLWsTest.java
index d222480f28..c8f6c83816 100644
--- a/tests/java-client/src/test/java/test/GraphQLWsTest.java
+++ b/tests/java-client/src/test/java/test/GraphQLWsTest.java
@@ -58,13 +58,13 @@ public class GraphQLWsTest {
   @Test
   public void queryOverWebSocket() {
     ApolloResponse<HelloQuery.Data> response = blockingQuery(apolloClient, HelloQuery.builder().build());
-    Truth.assertThat(response.dataAssertNoErrors().hello).isEqualTo("Hello World!");
+    Truth.assertThat(response.dataOrThrow().hello).isEqualTo("Hello World!");
   }
 
   @Test
   public void mutationOverWebSocket() {
     ApolloResponse<SetHelloMutation.Data> response = blockingMutation(apolloClient, SetHelloMutation.builder().build());
-    Truth.assertThat(response.dataAssertNoErrors().hello).isEqualTo("Hello Mutation!");
+    Truth.assertThat(response.dataOrThrow().hello).isEqualTo("Hello Mutation!");
   }
 
   @Test
@@ -77,7 +77,7 @@ public class GraphQLWsTest {
     ApolloDisposable disposable = apolloClient.subscription(new GreetingsSubscription()).enqueue(new ApolloCallback<GreetingsSubscription.Data>() {
       @Override
       public void onResponse(@NotNull ApolloResponse<GreetingsSubscription.Data> response) {
-        actual.add(response.dataAssertNoErrors().greetings);
+        actual.add(response.dataOrThrow().greetings);
         latch.countDown();
       }
     });
diff --git a/tests/java-tests/src/test/java/test/ClientTest.java b/tests/java-tests/src/test/java/test/ClientTest.java
index 3970c82815..476d96b3fa 100644
--- a/tests/java-tests/src/test/java/test/ClientTest.java
+++ b/tests/java-tests/src/test/java/test/ClientTest.java
@@ -70,18 +70,18 @@ public class ClientTest {
     ApolloResponse<GetRandomQuery.Data> queryResponse = Rx2Apollo.single(
         apolloClient.query(GetRandomQuery.builder().build())
     ).blockingGet();
-    Truth.assertThat(queryResponse.dataAssertNoErrors().random).isEqualTo(42);
+    Truth.assertThat(queryResponse.dataOrThrow().random).isEqualTo(42);
 
     mockServer.enqueue(new MockResponse.Builder().body("{\"data\": {\"createAnimal\": {\"__typename\": \"Cat\", \"species\": \"cat\", \"habitat\": {\"temperature\": 10.5}}}}").build());
     ApolloResponse<CreateCatMutation.Data> mutationResponse = Rx2Apollo.single(
         apolloClient.mutation(CreateCatMutation.builder().build())
     ).blockingGet();
-    Truth.assertThat(mutationResponse.dataAssertNoErrors().createAnimal.catFragment.species).isEqualTo("cat");
+    Truth.assertThat(mutationResponse.dataOrThrow().createAnimal.catFragment.species).isEqualTo("cat");
 
     Disposable disposable = Rx2Apollo.flowable(
         apolloClient.subscription(AnimalCreatedSubscription.builder().build())
     ).subscribe(result -> {
-      String species = result.dataAssertNoErrors().animalCreated.catFragment.species;
+      String species = result.dataOrThrow().animalCreated.catFragment.species;
     });
   }
 
diff --git a/tests/multipart/src/commonTest/kotlin/test/MultipartSubscriptionsFakeTest.kt b/tests/multipart/src/commonTest/kotlin/test/MultipartSubscriptionsFakeTest.kt
index 770c900ef7..6886d9e41d 100644
--- a/tests/multipart/src/commonTest/kotlin/test/MultipartSubscriptionsFakeTest.kt
+++ b/tests/multipart/src/commonTest/kotlin/test/MultipartSubscriptionsFakeTest.kt
@@ -51,7 +51,7 @@ class MultipartSubscriptionsFakeTest {
         CounterSubscription.Data(CounterSubscription.Counter(3)),
     )
 
-    val actualDataList = apolloClient.subscription(CounterSubscription()).toFlow().toList().map { it.dataAssertNoErrors }
+    val actualDataList = apolloClient.subscription(CounterSubscription()).toFlow().toList().map { it.dataOrThrow() }
 
     assertContentEquals(expectedDataList, actualDataList)
   }
diff --git a/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt b/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt
index c44f0e2768..2ab2c597c1 100644
--- a/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt
+++ b/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt
@@ -48,7 +48,7 @@ class NormalizationTest {
 
     val query = Issue3672Query()
 
-    val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse).jsonReader(), CustomScalarAdapters.Empty).dataAssertNoErrors
+    val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse).jsonReader(), CustomScalarAdapters.Empty).dataOrThrow()
     store.writeOperation(query, data1)
 
     val data2 = store.readOperation(query)
@@ -65,7 +65,7 @@ class NormalizationTest {
 
     val query = NestedFragmentQuery()
 
-    val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse_list).jsonReader(), CustomScalarAdapters.Empty).dataAssertNoErrors
+    val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse_list).jsonReader(), CustomScalarAdapters.Empty).dataOrThrow()
     store.writeOperation(query, data1)
 
     val data2 = store.readOperation(query)
diff --git a/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt b/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt
index 2304972631..d11e660ecd 100644
--- a/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt
+++ b/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt
@@ -11,6 +11,6 @@ import java.io.File
 class OutOfBoundsTest {
   @Test
   fun checkOutOfBounds() {
-    GetAnimalQuery().parseJsonResponse(File("src/main/json/response.json").source().buffer().jsonReader()).dataAssertNoErrors
+    GetAnimalQuery().parseJsonResponse(File("src/main/json/response.json").source().buffer().jsonReader()).dataOrThrow()
   }
 }
\ No newline at end of file
diff --git a/tests/scalar-adapters/src/test/kotlin/test/CustomScalarTest.kt b/tests/scalar-adapters/src/test/kotlin/test/CustomScalarTest.kt
index 57ea518d87..df5c85568a 100644
--- a/tests/scalar-adapters/src/test/kotlin/test/CustomScalarTest.kt
+++ b/tests/scalar-adapters/src/test/kotlin/test/CustomScalarTest.kt
@@ -49,7 +49,7 @@ class CustomScalarTest {
     val data = ApolloClient.Builder().serverUrl(serverUrl = server.url()).build()
         .query(BuiltInAdaptersQuery())
         .execute()
-        .dataAssertNoErrors
+        .dataOrThrow()
     assertEquals(1L, data.id)
     assertNull(data.nullableId)
     assertEquals(10_000_000_000L, data.long)
@@ -85,7 +85,7 @@ class CustomScalarTest {
     val data = ApolloClient.Builder().serverUrl(serverUrl = server.url()).build()
         .query(CompileTimeAdaptersQuery())
         .execute()
-        .dataAssertNoErrors
+        .dataOrThrow()
 
     assertEquals("string", data.string.value)
     assertNull(data.nullableString)
@@ -110,7 +110,7 @@ class CustomScalarTest {
         .build()
         .query(DecimalQuery())
         .execute()
-        .dataAssertNoErrors
+        .dataOrThrow()
 
     assertEquals("1000000000000000000000000000000000000000000", data.decimal?.toString())
   }
@@ -155,7 +155,7 @@ class CustomScalarTest {
         .build()
         .query(AddressQuery())
         .execute()
-        .dataAssertNoErrors
+        .dataOrThrow()
 
     assertEquals(Address("Downing Street", 10), data.address)
   }
diff --git a/tests/test-network-transport/src/test/kotlin/testnetworktransport/CustomTestNetworkTransportHandlerTest.kt b/tests/test-network-transport/src/test/kotlin/testnetworktransport/CustomTestNetworkTransportHandlerTest.kt
index 2ec53501af..0a1e332bd0 100644
--- a/tests/test-network-transport/src/test/kotlin/testnetworktransport/CustomTestNetworkTransportHandlerTest.kt
+++ b/tests/test-network-transport/src/test/kotlin/testnetworktransport/CustomTestNetworkTransportHandlerTest.kt
@@ -4,6 +4,7 @@ import com.apollographql.apollo3.ApolloClient
 import com.apollographql.apollo3.api.ApolloRequest
 import com.apollographql.apollo3.api.ApolloResponse
 import com.apollographql.apollo3.api.Operation
+import com.apollographql.apollo3.exception.DefaultApolloException
 import com.apollographql.apollo3.network.NetworkTransport
 import com.apollographql.apollo3.testing.enqueueTestResponse
 import com.apollographql.apollo3.testing.internal.runTest
@@ -58,15 +59,15 @@ class CustomTestNetworkTransportHandlerTest {
     val actual0 = apolloClient.query(query).execute()
     val actual1 = apolloClient.query(query).execute()
     val actual2 = apolloClient.query(query).execute()
-    assertEquals("Droid 0", actual0.dataAssertNoErrors.hero.name)
-    assertEquals("Droid 1", actual1.dataAssertNoErrors.hero.name)
-    assertEquals("Droid 2", actual2.dataAssertNoErrors.hero.name)
+    assertEquals("Droid 0", actual0.dataOrThrow().hero.name)
+    assertEquals("Droid 1", actual1.dataOrThrow().hero.name)
+    assertEquals("Droid 2", actual2.dataOrThrow().hero.name)
   }
 
   @Test
   fun registerAndQueueMethodsFail() = runTest(before = { setUp() }, after = { tearDown() }) {
     assertFailsWith(IllegalStateException::class) {
-      apolloClient.enqueueTestResponse(ApolloResponse.Builder(GetHeroQuery("id"), uuid4(), null).build())
+      apolloClient.enqueueTestResponse(ApolloResponse.Builder(GetHeroQuery("id"), uuid4(), DefaultApolloException()).build())
     }
     assertFailsWith(IllegalStateException::class) {
       apolloClient.registerTestResponse(GetHeroQuery("id"), null)
diff --git a/tests/test-network-transport/src/test/kotlin/testnetworktransport/MapTestNetworkTransportHandlerTest.kt b/tests/test-network-transport/src/test/kotlin/testnetworktransport/MapTestNetworkTransportHandlerTest.kt
index 7d56c80a2b..3151a18b74 100644
--- a/tests/test-network-transport/src/test/kotlin/testnetworktransport/MapTestNetworkTransportHandlerTest.kt
+++ b/tests/test-network-transport/src/test/kotlin/testnetworktransport/MapTestNetworkTransportHandlerTest.kt
@@ -29,14 +29,18 @@ class MapTestNetworkTransportHandlerTest {
   @Test
   fun registerResponses() = runTest(before = { setUp() }, after = { tearDown() }) {
     val query1 = GetHeroQuery("001")
-    val testResponse1 = ApolloResponse.Builder(query1, uuid4(), null)
-        .errors(listOf(Error(
+    val testResponse1 = ApolloResponse.Builder(
+        operation = query1,
+        requestUuid = uuid4(),
+        data = null,
+        errors = listOf(Error(
             message = "There was an error",
             locations = listOf(Error.Location(line = 1, column = 2)),
             path = listOf("hero", "name"),
             extensions = null,
-            nonStandardFields = null))
-        ).build()
+            nonStandardFields = null)),
+        extensions = null
+    ).build()
 
     val query2 = GetHeroQuery("002")
     val query2TestData = GetHeroQuery.Data(
diff --git a/tests/test-network-transport/src/test/kotlin/testnetworktransport/QueueTestNetworkTransportHandlerTest.kt b/tests/test-network-transport/src/test/kotlin/testnetworktransport/QueueTestNetworkTransportHandlerTest.kt
index d1b57c2731..8123d33c37 100644
--- a/tests/test-network-transport/src/test/kotlin/testnetworktransport/QueueTestNetworkTransportHandlerTest.kt
+++ b/tests/test-network-transport/src/test/kotlin/testnetworktransport/QueueTestNetworkTransportHandlerTest.kt
@@ -31,14 +31,18 @@ class QueueTestNetworkTransportHandlerTest {
   @Test
   fun enqueueResponses() = runTest(before = { setUp() }, after = { tearDown() }) {
     val query1 = GetHeroQuery("001")
-    val testResponse1 = ApolloResponse.Builder(query1, uuid4(), null)
-        .errors(listOf(Error(
+    val testResponse1 = ApolloResponse.Builder(
+        operation = query1,
+        requestUuid = uuid4(),
+        data = null,
+        errors = listOf(Error(
             message = "There was an error",
             locations = listOf(Error.Location(line = 1, column = 2)),
             path = listOf("hero", "name"),
             extensions = null,
-            nonStandardFields = null))
-        ).build()
+            nonStandardFields = null)),
+        extensions = null
+    ).build()
 
     val query2 = GetHeroQuery("002")
     val query2TestData = GetHeroQuery.Data(
diff --git a/tests/websockets/src/jvmTest/kotlin/WebSocketErrorsTest.kt b/tests/websockets/src/jvmTest/kotlin/WebSocketErrorsTest.kt
index dd4b9b1d62..d9b10a7538 100644
--- a/tests/websockets/src/jvmTest/kotlin/WebSocketErrorsTest.kt
+++ b/tests/websockets/src/jvmTest/kotlin/WebSocketErrorsTest.kt
@@ -114,7 +114,7 @@ class WebSocketErrorsTest {
       apolloClient.subscription(CountSubscription(2, 500))
           .toFlow()
           .map {
-            it.dataAssertNoErrors.count
+            it.dataOrThrow().count
           }
           .toList()
     }
@@ -140,7 +140,7 @@ class WebSocketErrorsTest {
     // Trigger an error
     val response = apolloClient.query(CloseSocketQuery()).execute()
 
-    assertEquals(response.dataAssertNoErrors.closeWebSocket, "Closed 1 session(s)")
+    assertEquals(response.dataOrThrow().closeWebSocket, "Closed 1 session(s)")
 
     /**
      * The subscription should be restarted and complete successfully the second time
@@ -180,7 +180,7 @@ class WebSocketErrorsTest {
     delay(1000)
     val response = apolloClient.query(CloseSocketQuery()).execute()
 
-    println(response.dataAssertNoErrors)
+    println(response.dataOrThrow())
   }
 
   @Test
@@ -205,7 +205,7 @@ class WebSocketErrorsTest {
     apolloClient.subscription(CountSubscription(2, 500))
         .toFlow()
         .map {
-          it.dataAssertNoErrors.count
+          it.dataOrThrow().count
         }
         .test {
           awaitItem()