Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UndeliverableException with RxJava3 and Retrofit2 #4144

Open
Raygooo opened this issue May 20, 2024 · 1 comment
Open

UndeliverableException with RxJava3 and Retrofit2 #4144

Raygooo opened this issue May 20, 2024 · 1 comment

Comments

@Raygooo
Copy link

Raygooo commented May 20, 2024

Hi there,

There is an strange crash in our android car application due to UndeliverableException.

we are using kotlin with rxjava
retrofit2/retrofit2:adapter-rxjava3 version: 2.9.0
rxjava/rxkotlin/rxandroid version: 3.0.0

I have reviewed the following issues:
#2487
ReactiveX/RxJava#6249

These issues mention using the zip operator when multiple sources encounter errors simultaneously. In such cases, each observable source from Retrofit attempts to emit an error downstream, but only one error is passed down normally, while the others are handled by RxJava's global ErrorHandler.

However, this doesn't seem to be the case here.

In my situation, I called the Retrofit service within a switchMap, adding logs (though no logs indicate it re-entered). Then, I used a retryWhen with logs (again, no logs indicate it ever entered), and finally, an onErrorReturn with logs, but no logs were printed for that either.

        upperStream
            .switchMap {
                    // log (print once)
                   myService
                      .getMyTrip(xxx, token)
                      .switchMap<Action> { resultList ->
                            // log sucess and bussiness logic with next item, (no print here)
                      }
                }.retryWhen { observable ->
                    // log and retry logic (no print here)
                }.onErrorReturn {
                    // log and with failed item (no print here)
                }
            }

I looked into some of the retrofit souce code according to the exception trace, I found that

    @Override
    public void onFailure(Call<T> call, Throwable t) {
      if (call.isCanceled()) return;

      try {
        observer.onError(t);
      } catch (Throwable inner) {
        Exceptions.throwIfFatal(inner);
        RxJavaPlugins.onError(new CompositeException(t, inner));
      }
    }

I'm not sure if replacing onError with tryOnError aligns with the retrofit/rxjava design purpose, but it seems it could avoid the error (though that might not be the right approach :P).

I could work around this issue similarly to the two issues mentioned: by adding a global ErrorHandler and ignoring the socketException once and for all. However, I still wouldn't know what the root cause is.

Any help or insights would be greatly appreciated! Thanks in advance!

System.err[4098]: 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 xxx.com/xxx.xxx:443
System.err[4098]: 	at io.reactivex.rxjava3.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:8)
System.err[4098]: 	at io.reactivex.rxjava3.internal.util.AtomicThrowable.tryAddThrowableOrReport(AtomicThrowable.java:2)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.onError(ObservableFlatMap.java:3)
System.err[4098]: 	at io.reactivex.rxjava3.internal.util.AtomicThrowable.tryTerminateConsumer(AtomicThrowable.java:8)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.checkTerminate(ObservableFlatMap.java:5)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.drainLoop(ObservableFlatMap.java:2)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.drain(ObservableFlatMap.java:2)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$InnerObserver.onError(ObservableFlatMap.java:5)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableError.subscribeActual(ObservableError.java:4)
System.err[4098]: 	at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:8)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:34)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:10)
System.err[4098]: 	at io.reactivex.rxjava3.subjects.PublishSubject.onNext(PublishSubject.java:4)
System.err[4098]: 	at io.reactivex.rxjava3.subjects.SerializedSubject.onNext(SerializedSubject.java:13)
System.err[4098]: 	at io.reactivex.rxjava3.internal.operators.observable.ObservableRetryWhen$RepeatWhenObserver.onError(ObservableRetryWhen.java:3)
System.err[4098]: 	at io.reactivex.rxjava3.internal.observers.BasicFuseableObserver.onError(BasicFuseableObserver.java:4)
System.err[4098]: 	at retrofit2.adapter.rxjava3.BodyObservable$BodyObserver.onError(BodyObservable.java:2)
System.err[4098]: 	at retrofit2.adapter.rxjava3.CallEnqueueObservable$CallCallback.onFailure(CallEnqueueObservable.java:2)
System.err[4098]: 	at retrofit2.OkHttpCall$1.onFailure(OkHttpCall.java:1)
System.err[4098]: 	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:15)
System.err[4098]: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
System.err[4098]: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
System.err[4098]: 	at java.lang.Thread.run(Thread.java:920)
System.err[4098]: Caused by: java.net.ConnectException: Failed to connect to xxx.com/xxx.xxx:443
System.err[4098]: 	at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:14)
System.err[4098]: 	at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:16)
System.err[4098]: 	at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:39)
System.err[4098]: 	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:1)
System.err[4098]: 	at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:7)
System.err[4098]: 	at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:8)
System.err[4098]: 	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:2)
System.err[4098]: 	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:12)
System.err[4098]: 	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:27)
System.err[4098]: 	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:12)
System.err[4098]: 	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:22)
System.err[4098]: 	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:12)
System.err[4098]: 	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:7)
System.err[4098]: 	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:12)
System.err[4098]: 	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:16)
System.err[4098]: 	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:6)
System.err[4098]: 	... 3 more
System.err[4098]: Caused by: java.net.ConnectException: failed to connect to xxx.com/xxx.xxx: (port 443) from /10.48.199.126 (port 51156) after 15000ms: isConnected failed: ECONNREFUSED (Connection refused)
System.err[4098]: 	at libcore.io.IoBridge.isConnected(IoBridge.java:349)
System.err[4098]: 	at libcore.io.IoBridge.connectErrno(IoBridge.java:238)
System.err[4098]: 	at libcore.io.IoBridge.connect(IoBridge.java:180)
System.err[4098]: 	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
System.err[4098]: 	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
System.err[4098]: 	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
System.err[4098]: 	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
System.err[4098]: 	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
System.err[4098]: 	at java.net.Socket.connect(Socket.java:621)
System.err[4098]: 	at okhttp3.internal.platform.Platform.connectSocket(Platform.kt:1)
System.err[4098]: 	at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:9)
System.err[4098]: 	... 18 more
System.err[4098]: Caused by: android.system.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
System.err[4098]: 	at libcore.io.IoBridge.isConnected(IoBridge.java:336)
System.err[4098]: 	... 28 more
@JakeWharton
Copy link
Member

I'm out for a week. Will try to look next week when I return.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants