Kotlin 1.4.10 and ClassCastException while using coroutines

Viewed 703

After upgrade to Kotlin 1.4.10, my Android application started to throw exceptions while using coroutines. My code:

class CollectionBookRepositoryImpl @Inject constructor(
    @CollectionBookReference private val reference: DatabaseReference,
) : CollectionBookRepository {

    override suspend fun add(book: CollectionBook): Result<Unit> {
        return runCatching {
            reference.setValue(book).await()
        }
    }
}

class AddCollectionBookUseCaseImpl @Inject constructor(
    private val collectionBookRepository: CollectionBookRepository,
) : AddCollectionBookUseCase {

    override suspend fun invoke(input: CollectionBook): Result<Unit> =
        collectionBookRepository.add(input)
}

class BookEditViewModel @Inject constructor(
    private val addCollectionBook: AddCollectionBookUseCase,
) : BaseViewModel() {

    fun addBook() {
        val book = CollectionBook()

        viewModelScope.launch(Dispatchers.IO) {
            val result = addCollectionBook(book)
            if (result.isSuccess) {
                _state.postValue(BookEditState.BookAdded)
            } else {
                val errorState = BookEditState.Error(R.string.adding_book_error_message)
                _state.postValue(errorState)
            }
        }
    }
}

Invoking addBook() method in ViewModel causes application crash. Stacktrace of exception:

pl.kamilszustak.read E/AndroidRuntime: FATAL EXCEPTION: main
    Process: pl.kamilszustak.read, PID: 2327
    kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[Dispatchers.IO, Continuation at pl.kamilszustak.read.data.repository.CollectionBookRepositoryImpl.add-d1pmJ48(CollectionBookRepositoryImpl.kt:21)@e2bea4b]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
        at kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(DispatchedTask.kt:93)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:64)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.ClassCastException: kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.DispatchedContinuation
        at kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.kt:103)
        at kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.kt:118)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:39)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:55)
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

Moreover, when I change addBook() method to:

fun addBook() {
    val book = CollectionBook()

    addCollectionBook(book)
        .onSuccess {
            _state.postValue(BookEditState.BookAdded)
        }
        .onFailure {
            val errorState = BookEditState.Error(R.string.adding_book_error_message)
            _state.postValue(errorState)
        }
}

it throws:

pl.kamilszustak.read E/AndroidRuntime: FATAL EXCEPTION: main
    Process: pl.kamilszustak.read, PID: 5355
    java.lang.ClassCastException: kotlin.coroutines.intrinsics.CoroutineSingletons cannot be cast to kotlin.Unit
        at pl.kamilszustak.read.ui.main.book.edit.BookEditViewModel$addBook$1.invokeSuspend(BookEditViewModel.kt:82)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:333)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
        at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
        at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
        at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:49)
        at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
        at pl.kamilszustak.read.ui.main.book.edit.BookEditViewModel.addBook(BookEditViewModel.kt:80)

Is it even possible to fix without any update from Kotlin authors?

0 Answers
Related