'RxJava: UndeliverableException when flatMap combined with switchMap

TL;DR

I think that flatMap combined with switchMap might not terminate the stream correctly, thus UndeliverableException happens. How can I fix this?

The Structure

I'm making a little bit complex stream -- combined with flatMap and switchMap -- like below, in RxKotlin (RxJava 3):

someObservable
    .flatMapMaybe {
        if (matchCondition(it)) Maybe.just(it)
        else Maybe.never()
    }.flatMapSingle {
        procedureMiddle(it) // Inconsistent-time-consuming Single
    }.switchMap {
        procedureLater(it)
    }.doOnError {
        dealWithError(e)
    }.retry()
    .subscribeBy(
        // ...
    )

The procedureMiddle inside flatMapSingle has a chance of returning Error in the end.

The Exception

It turns out that sometimes the error from procedureMiddle might jump out of structure, not being ignored by retry, nor dealt in dealWithError in doOnError:

W/System.err: 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 | my.custom.app.CustomException
// traces indicates that the Exception is thrown from inside procedureMiddle

The Question

In fact the UndeliverableException doesn't really cause crash, but it's a little bit annoying for me --especially it looks like a situation I need to handle. However I thought the structure is correctly written? So here's my question:

  1. Does switchMap really (correctly) terminate the last stream from flatMap? (And can be used to prevent UndeliverableException?)
  2. If so, at which part of code I should adjust? If not so, how could I prevent the exceptions along with my structure? (I want to concat procedureLater after procedureMiddle, and keep only latest one)

Any suggestion or explanation would be helpful.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source