Hello hello! Got a doubt regarding apollo v4 excep...
# apollo-kotlin
m
Hello hello! Got a doubt regarding apollo v4 exception handling and authentications 🧵
Copy code
suspend fun <D : Operation.Data> ApolloCall<D>.executeAsResult(): Result<D> = with(execute()) {
    val requestId = findRequestIdHeader()
    when {
        hasErrors() -> {
            val message = errors?.joinToString { it.message }
            Result.failure(KrakenFieldClientException(message.orEmpty()))
        }

        exception != null -> Result.failure(
            wrapResponseException(
                exception = exception!!,
                requestId = requestId,
                operation = operation,
            ),
        )

        data != null -> Result.success(data!!)

        else -> {
            Result.failure(KrakenFieldNotCompliantServerException("No data or errors in response"))
        }
    }
}
We wrote the following extensions tu execute queries/mutaiton and return a result of the operation. We used to use try cat but afaik with apollo 4 apollo shoudl not throw and rather use
exception
field
so far so good
the problem is that we also have an authenticator added to the client, which at some point we attempt at re authenticate the user. For that call we only catch one exception we are interested in and let the other bubble up
Our assumption was that because the authenticator is added to the client internal machinery of the client, any exception thrown there would be handled by it and be part of the exception field mentioned above.
But we've been doing some tests and it seems that thats not the case and the exception is re thrown ( thus breaking our original as result function
Is this correct?
m
we also have an authenticator added to the client
That's OkHttp, right?
Any exception thrown by OkHttp should be caught here and exposed in
ApolloResponse.exception
So I'm tempted to say your expectations are correct.
But if you're seeing an exception that is not handled then obviously something is off somewhere
m
Its an ApolloInterceptor actually
m
Gotcha yea, that one shouldn't throw
You can return an exception response to the upstream interceptors
But throwing will tear the interceptor chain down
m
> Gotcha yea, that one shouldn't throw As in us devs should not be throwing within the interceptor, or as in if something its thrown its handled eventually with the exception field of the response
m
If
ApolloInterceptor.intercept()
throws, nothing is going to catch the exception to turn in into an
exception
field
If OkHttp throws, your interceptor receives an
exception response
m
cristal clear! thanks for the speedy response
m
Sure thing!
m
You can return an exception response to the upstream interceptors
This bit is not fully clear
How could I return such a response from the intercept method?
m
You can use
ApolloResponse.Builder.exception()
🙌 1
m
I see! Perfect thanks
m
For an exemple, this is done here
(No need to do the
isLast()
dance, this is something I'm trying to remove actually)
Copy code
try {
              // do your stuff here
            } catch (e: Exception) {
              return flowOf(
                  ApolloResponse.Builder(request.operation, request.requestUuid)
                  .exception(exception)
                  .build()
              )
            }
m
Noted, much appreciated!
🙌 1
So the exception property takes only an apollo exception, we do
Copy code
DefaultApolloException(
                                message = e.message,
                                cause = e,
                            )
Altho it feels a bit nasty. I guess we can only catch ApolloExceptions
m
Agree, this is awkward but very hard to change.
DefaultApolloException
is the way to go
Idea was to give a base class to make exception more discoverable but that didn't age well.
m
Makes sense, thats ok we'll go with this approach and soem docs. Cheers again! Enjoy your afternoon
thank you color 1