apollographql / apollo-kotlin

:rocket:  A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
https://www.apollographql.com/docs/kotlin
MIT License
3.75k stars 651 forks source link

Fatal Exception: java.io.IOException failed to delete /data/user/0/com.example.mobile/cache/http-cache/63e602c86c6aa918b680ba2f111c3fa9.1 #5722

Closed GRabia closed 7 months ago

GRabia commented 7 months ago

Version

3.8.2

Summary

Android app has been updated from Apollo 2.5.14 to 3.8.2 And now that I've moved, I'm receiving this error. I can't figure out the precise code where is coming from, nor can I reproduce it. However I am suspecting it is from apolloClient.apolloStore.clearAll() or apolloClient.httpCache.clearAll(), I added a try catch block to attempt and catch this exception while clearing the cache upon logout, but it was unsuccessful, and the crash continued.

-------------------This crash occurs, with Android 10 and above only ---------------

Happened recently on this device: Brand:Google Model:Pixel 7a Orientation:Portrait RAM free: 1.23 GB Disk free: 28.9 GB Operating System Version:Android 14

Steps to reproduce the behavior

Non-Reproducible

Logs

Fatal Exception: java.io.IOException: failed to delete /data/user/0/com.example.mobile/cache/http-cache/63e602c86c6aa918b680ba2f111c3fa9.1
       at okio.JvmSystemFileSystem.delete(JvmSystemFileSystem.kt:129)
       at okio.FileSystem.delete(FileSystem.kt:114)
       at com.apollographql.apollo3.cache.http.internal.DiskLruCacheKt.delete(DiskLruCache.kt:1018)
       at com.apollographql.apollo3.cache.http.internal.DiskLruCacheKt.access$delete(DiskLruCache.kt:1)
       at com.apollographql.apollo3.cache.http.internal.DiskLruCache.removeEntry(DiskLruCache.kt:560)
       at com.apollographql.apollo3.cache.http.internal.DiskLruCache.remove(DiskLruCache.kt:549)
       at com.apollographql.apollo3.cache.http.DiskLruHttpCache.remove(DiskLruHttpCache.kt:103)
       at com.apollographql.apollo3.cache.http.HttpCache$httpCache$2$intercept$1$2.invokeSuspend(HttpCacheExtensions.kt:132)
       at com.apollographql.apollo3.cache.http.HttpCache$httpCache$2$intercept$1$2.invoke(:8)
       at com.apollographql.apollo3.cache.http.HttpCache$httpCache$2$intercept$1$2.invoke(:4)
       at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:223)
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$2.emit(Errors.kt:158)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:87)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
       at com.apollographql.apollo3.cache.normalized.FetchPolicyInterceptors$CacheAndNetworkInterceptor$1$intercept$1$invokeSuspend$$inlined$map$1$2.emit(Emitters.kt:223)
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$2.emit(Errors.kt:158)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:87)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
       at com.apollographql.apollo3.cache.normalized.internal.ApolloCacheInterceptor$readFromNetwork$$inlined$map$1$2.emit(Emitters.kt:223)
       at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:224)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:87)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
       at com.apollographql.apollo3.network.http.HttpNetworkTransport$execute$1.invokeSuspend(HttpNetworkTransport.kt:90)
       at com.apollographql.apollo3.network.http.HttpNetworkTransport$execute$1.invoke(:8)
       at com.apollographql.apollo3.network.http.HttpNetworkTransport$execute$1.invoke(:4)
       at kotlinx.coroutines.flow.SafeFlow.collectSafely(Builders.kt:61)
       at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:230)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperatorImpl.flowCollect(ChannelFlow.kt:195)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collect$suspendImpl(ChannelFlow.kt:167)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collect()
       at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1.collect(SafeCollector.common.kt:113)
       at com.apollographql.apollo3.cache.normalized.internal.ApolloCacheInterceptor$readFromNetwork$$inlined$map$1.collect(SafeCollector.common.kt:113)
       at kotlinx.coroutines.flow.FlowKt__CollectKt.emitAll(Collect.kt:109)
       at kotlinx.coroutines.flow.FlowKt.emitAll(:1)
       at com.apollographql.apollo3.cache.normalized.internal.ApolloCacheInterceptor$interceptQuery$1.invokeSuspend(ApolloCacheInterceptor.kt:196)
       at com.apollographql.apollo3.cache.normalized.internal.ApolloCacheInterceptor$interceptQuery$1.invoke(:8)
       at com.apollographql.apollo3.cache.normalized.internal.ApolloCacheInterceptor$interceptQuery$1.invoke(:4)
       at kotlinx.coroutines.flow.SafeFlow.collectSafely(Builders.kt:61)
       at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:230)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperatorImpl.flowCollect(ChannelFlow.kt:195)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collect$suspendImpl(ChannelFlow.kt:167)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collect()
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt.catchImpl(Errors.kt:156)
       at kotlinx.coroutines.flow.FlowKt.catchImpl(:1)
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catch$$inlined$unsafeFlow$1.collect(SafeCollector.common.kt:113)
       at com.apollographql.apollo3.cache.normalized.FetchPolicyInterceptors$CacheAndNetworkInterceptor$1$intercept$1$invokeSuspend$$inlined$map$1.collect(SafeCollector.common.kt:113)
       at kotlinx.coroutines.flow.FlowKt__CollectKt.emitAll(Collect.kt:109)
       at kotlinx.coroutines.flow.FlowKt.emitAll(:1)
       at com.apollographql.apollo3.cache.normalized.FetchPolicyInterceptors$CacheAndNetworkInterceptor$1$intercept$1.invokeSuspend(FetchPolicyInterceptors.kt:211)
       at com.apollographql.apollo3.cache.normalized.FetchPolicyInterceptors$CacheAndNetworkInterceptor$1$intercept$1.invoke(:8)
       at com.apollographql.apollo3.cache.normalized.FetchPolicyInterceptors$CacheAndNetworkInterceptor$1$intercept$1.invoke(:4)
       at kotlinx.coroutines.flow.SafeFlow.collectSafely(Builders.kt:61)
       at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:230)
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt.catchImpl(Errors.kt:156)
       at kotlinx.coroutines.flow.FlowKt.catchImpl(:1)
       at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catch$$inlined$unsafeFlow$1.collect(SafeCollector.common.kt:113)
       at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1.collect(SafeCollector.common.kt:113)
       at kotlinx.coroutines.flow.FlowKt__EmittersKt$onCompletion$$inlined$unsafeFlow$1.collect(SafeCollector.common.kt:114)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperatorImpl.flowCollect(ChannelFlow.kt:195)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo$suspendImpl(ChannelFlow.kt:157)
       at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo()
       at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:60)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664) 
BoD commented 7 months ago

Thanks for reporting this!

From the stacktrace, it appears that this actually happens when executing a query. The cache interceptor is trying to delete a cached response from the disk cache, and fails - probably due to some I/O error. This should probably be caught inside the interceptor instead of being thrown - I will make a fix for that.

In the meantime, if you currently enclose your calls to execute() in a try catch you may want to broaden your catch clause from ApolloException to Exception to catch this one.

BoD commented 7 months ago

The fix is available in v3.8.3.

github-actions[bot] commented 7 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Kotlin usage and allow us to serve you better.