I am faciing an UndeliverableException case when using a Single.zip and multiple sources from retrofit fail to load the data from the network. I expected that when the first error happens the other streams would be disposed, but it seems it is not the case as the
io.reactivex.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.UnknownHostException: Unable to resolve host "my.domain.com": No address associated with hostname
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
at io.reactivex.internal.operators.single.SingleZipArray$ZipCoordinator.innerError(SingleZipArray.java:139)
at io.reactivex.internal.operators.single.SingleZipArray$ZipSingleObserver.onError(SingleZipArray.java:175)
at io.reactivex.internal.operators.single.SingleMap$MapSingleObserver.onError(SingleMap.java:69)
at io.reactivex.internal.observers.ResumeSingleObserver.onError(ResumeSingleObserver.java:51)
at io.reactivex.internal.disposables.EmptyDisposable.error(EmptyDisposable.java:78)
at io.reactivex.internal.operators.single.SingleError.subscribeActual(SingleError.java:42)
at io.reactivex.Single.subscribe(Single.java:3438)
at io.reactivex.internal.operators.single.SingleResumeNext$ResumeMainSingleObserver.onError(SingleResumeNext.java:80)
at io.reactivex.internal.operators.observable.ObservableSingleSingle$SingleElementObserver.onError(ObservableSingleSingle.java:93)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onError(ObservableSubscribeOn.java:63)
override fun getFieldsDetails(): Single<List<FieldDetail>> {
return service.getFields()
.flatMap { fields ->
if (fields.isEmpty()) {
Single.just(emptyList())
} else {
Single.zip(fields.map { field ->
service.getFieldDetail(field)
}) { it ->
it.filterIsInstance<FieldDetail>()
}
}
}
}
It looks like this issue from retrofit repo https://github.com/square/retrofit/issues/2487 . If that is not a retrofit problem, what can be done to avoid this crash?
Please read the exception message and the linked wiki section:
io.reactivex.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.UnknownHostException: Unable to resolve host "my.domain.com": No address associated with hostname
@akarnokd I have read the docs, but that does not seems to anwser my question.
Is this the expected behavior? If so, what can I do as developer to handle this from my side as from
setting an RxJavaPlugins.setErrorHandler seems to be an exagerad option.
If this is my ONLY option, how to keep the original error handling for other cases and still avoid the app to crash in this case?
The detailed error message and the wiki link has the implication that such cases are expected and you can't do much about them: either you set the global error handler or you don't crash into RxJava.
In your specific case, zip can only deal with one of its sources failing. If multiple sources fail, RxJava can't tell if those other exceptions are significant for you and it can call onError again either. Thus it goes to the last resort handler as described in the wiki.
private fun setRxJavaErrorHandler() {
RxJavaPlugins.setErrorHandler(Throwable::printStackTrace)
}
Most helpful comment
The detailed error message and the wiki link has the implication that such cases are expected and you can't do much about them: either you set the global error handler or you don't crash into RxJava.
In your specific case,
zipcan only deal with one of its sources failing. If multiple sources fail, RxJava can't tell if those other exceptions are significant for you and it can callonErroragain either. Thus it goes to the last resort handler as described in the wiki.