-
Notifications
You must be signed in to change notification settings - Fork 53
Description
Hello,
We are using the Contentful SDK, and very rarely we get a crash with the following stack trace:
Fatal Exception: io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.net.ConnectException: Failed to connect to cdn.contentful.com/151.101.39.18:443
at io.reactivex.rxjava3.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:372)
at io.reactivex.rxjava3.internal.subscribers.LambdaSubscriber.onError(LambdaSubscriber.java:85)
at io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish$PublishConnection.signalError(FlowablePublish.java:367)
at io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish$PublishConnection.checkTerminated(FlowablePublish.java:350)
at io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish$PublishConnection.drain(FlowablePublish.java:302)
at io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish$PublishConnection.onError(FlowablePublish.java:244)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableObserveOn$ObserveOnSubscriber.runBackfused(FlowableObserveOn.java:450)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableObserveOn$BaseObserveOnSubscriber.run(FlowableObserveOn.java:174)
at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:80)
at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by java.net.ConnectException: Failed to connect to cdn.contentful.com/151.101.39.18:443
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:297)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.java:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at com.contentful.java.cda.interceptor.ErrorInterceptor.intercept(ErrorInterceptor.java:31)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at com.contentful.java.cda.interceptor.HeaderInterceptor.intercept(HeaderInterceptor.java:38)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at com.contentful.java.cda.interceptor.HeaderInterceptor.intercept(HeaderInterceptor.java:38)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at com.contentful.java.cda.interceptor.HeaderInterceptor.intercept(HeaderInterceptor.java:38)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:207)
at retrofit2.adapter.rxjava3.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:46)
at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13263)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableFromObservable.subscribeActual(FlowableFromObservable.java:31)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16095)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onNext(FlowableFlatMap.java:161)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:69)
at io.reactivex.rxjava3.internal.subscriptions.ScalarSubscription.request(ScalarSubscription.java:55)
at io.reactivex.rxjava3.internal.subscribers.BasicFuseableSubscriber.request(BasicFuseableSubscriber.java:153)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onSubscribe(FlowableFlatMap.java:115)
at io.reactivex.rxjava3.internal.subscribers.BasicFuseableSubscriber.onSubscribe(BasicFuseableSubscriber.java:67)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableScalarXMap$ScalarXMapFlowable.subscribeActual(FlowableScalarXMap.java:158)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:38)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap.subscribeActual(FlowableFlatMap.java:51)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:38)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableObserveOn.subscribeActual(FlowableObserveOn.java:58)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16149)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:16095)
at io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish.connect(FlowablePublish.java:93)
at io.reactivex.rxjava3.flowables.ConnectableFlowable.connect(ConnectableFlowable.java:105)
at com.contentful.java.cda.Callbacks.subscribeAsync(Callbacks.java:21)
at com.contentful.java.cda.FetchQuery.all(FetchQuery.java:63)
at (our app's package)$suspendedAll$2.invokeSuspend(ContentfulFetcher.kt:82)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.java:113)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:586)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
It seems to be RxJava related. We're not doing anything in particular, we're just registering a FetchQuery with the all method. Something like:
private suspend fun <T : CDAResource> FetchQuery<T>.suspendedAll(): List<CDAResource> {
val callback = object : CDACallback<CDAArray>() {
override fun onSuccess(result: CDAArray) {
// Success
}
override fun onFailure(error: Throwable?) {
// Fail
}
}
// More code here where we might cancel the callback (via a Coroutines cancellation for example)
all(callback)
}Which is then used like:
client.fetch(CDAEntry::class.java)
.withContentType(contentType)
.include(level)
.where(/* some custom code here */)
.suspendedAll()Again, this happens very rarely - 3 times in the last 30 days, with slightly different network errors - and we have not been able to reproduce it. Querying Contentful with the device's network disabled just goes to the usual onFailure. But on very rare cases, it crashes in the all call, with a stack trace like the above - which we find on our crash monitoring.
Let me know if you need any further details on our implementation - sadly I can not share the actual code.
Thanks in advance!