Kotlinx.coroutines: AbstractMethodError when use withTimeout

Created on 15 Oct 2020  路  15Comments  路  Source: Kotlin/kotlinx.coroutines

I am getting the following error java.lang.AbstractMethodError: abstract method "kotlinx.coroutines.DisposableHandle kotlinx.coroutines.Delay.invokeOnTimeout(long, java.lang.Runnable, kotlin.coroutines.CoroutineContext)" when calling the withTimeout method into commonMain module.

    override suspend fun notifyCharacteristic(uuid: String, enabled: Boolean): Flow<ByteArray> {
        return withTimeout(2000) {
            bluetoothDataSource.watchConnectionState().filter {
                it == DeviceConnectionState.STATE_DISCOVERED
            }.first()

            val charac = retrieveCharacteristic(characteristics, uuid)
                ?: throw IllegalStateException("Characteristic is null")

            bluetoothDataSource.notifyCharacteristic(
                charac,
                enabled,
                "00002902-0000-1000-8000-00805f9b34fb"
            ).map { it.toByteArray() }
        }
    }

My project is configured in this way:

       getByName("commonMain") {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1")
            }
        }
        getByName("androidMain") {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1")
            }
        }
        getByName("iosMain") {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1")
            }
        }

Can be the notifyCharacteristic function bad written?

Thank you

waiting for clarification

Most helpful comment

@mkotyk

What platform? And which dependency are you using?

If on Android, I had the same issue and fixed it as follows:

Originally I used org.jetbrains.kotlinx:kotlinx-coroutines-core:, but reading comments here, I switched to org.jetbrains.kotlinx:kotlinx-coroutines-android:. That helped.

All 15 comments

Can you, please, check all the versions of dependencies in your project with gradlew dependencies and include there here?

Hello,

I checked all the version com gradlew dependencies but task returns nothing to me.

image

So, I checked all dependencies carefully. In android module the coroutine dependency was implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1"). After changing for implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0-M1") the AbstractMethodError stops.

But I noticed a strange behaviour in notifyCharacteristic function. The withTimeout never throws the TimeoutCancellationException . I am reading the documentation to understanding if that it is correct.

For what its worth I also got this error:

java.lang.AbstractMethodError: abstract method "kotlinx.coroutines.DisposableHandle kotlinx.coroutines.Delay.invokeOnTimeout(long, java.lang.Runnable, kotlin.coroutines.CoroutineContext)"
        at kotlinx.coroutines.selects.SelectBuilderImpl.onTimeout(Select.kt:652)
        at kotlinx.coroutines.flow.FlowKt__DelayKt$debounce$2.invokeSuspend(Delay.kt:88)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.selects.SelectBuilderImpl.resumeWith(Select.kt:300)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
        at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:349)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:27)
        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 kotlinx.coroutines.flow.FlowKt__CollectKt.launchIn(Collect.kt:49)
        at kotlinx.coroutines.flow.FlowKt.launchIn(Unknown Source:1)

Initially I depended on:

def COROUTINES_VERSION = "1.4.0-M1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${COROUTINES_VERSION}"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:${COROUTINES_VERSION}"

But problem went away after depending on this one:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${COROUTINES_VERSION}"

Not sure what to make of it :man_shrugging:. This is a plain android kotlin project and in coroutines 1.3.9 this exception was not thrown.

Likely a version mismatch like in #1033

I'm seeing this too, and it's related to using debounce with 1.4.0 ... once I took the debounce out, the crash stopped.

Here's my usage:

 val showBiometricsPrompt: LiveData<ShowBiometricsPrompt?>
        get() = combine(_username.debounce(250), enrollingBiometrics) { a, b -> a to b }
            .map { (username, enrollingBiometrics) ->
                if (biometricsAvailable() is BiometricsAvailable.Result.Yes &&
                    (enrollingBiometrics || biometricsEnabledForUser(BiometricsEnabledForUser.Request(username)) is BiometricsEnabledForUser.Result.Yes)
                ) {
                    ShowBiometricsPrompt(username, enrollingBiometrics)
                } else {
                    null
                }
            }
            .asLiveData()

@mkotyk

What platform? And which dependency are you using?

If on Android, I had the same issue and fixed it as follows:

Originally I used org.jetbrains.kotlinx:kotlinx-coroutines-core:, but reading comments here, I switched to org.jetbrains.kotlinx:kotlinx-coroutines-android:. That helped.

That did the trick @lukas1. thanks for the solution! 馃檱

@elizarov, any clarifications for this issue?

All I can say is there is some versions mismatch between the coroutines modules in the project. Were you able to fix it or do you still need help?

I've came across this issue when I was working on Mockk tests in my project. In my case, it was caused by different versions of org.jetbrains.kotlinx:kotlinx-coroutines-android and org.jetbrains.kotlinx:kotlinx-coroutines-test. Updating both of them to 1.4.1 fixed the issue, maybe it will help somenone.

Got the same exception on the Android platform, no clue at first glance. It turned out was the suspend network function get called on the main Dispatchers. Just move the function to the Dispatchers.IO block and AbstractMethodError was gone.

java.lang.AbstractMethodError: abstract method "kotlinx.coroutines.DisposableHandle kotlinx.coroutines.Delay.invokeOnTimeout(long, java.lang.Runnable, kotlin.coroutines.CoroutineContext)"
at kotlinx.coroutines.test.internal.TestMainDispatcher.invokeOnTimeout(MainTestDispatcher.kt:50)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:145)
at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:44)
at com.hpb.laucher.LauncherViewModel$checkAvailableUpdate$2$1.invokeSuspend(LauncherViewModel.kt:73)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)

        launch {
            try {
                checkAvailableUpdate().await() // exception thrown 
                onboardingCompletedResult.value = withContext(Dispatchers.IO) {
                    launcherUseCase(Unit)
                }
            } catch (error: Throwable) {
                Timber.d(error)
            }
        }

The coroutines dependency declared in build.gradle: org.jetbrains.kotlinx:kotlinx-coroutines-android:$versions.coroutines, the version is 1.3.3.

Also get the same exception, when updated from 1.3.9 to 1.4.2

java.lang.AbstractMethodError: abstract method "kotlinx.coroutines.DisposableHandle kotlinx.coroutines.Delay.invokeOnTimeout(long, java.lang.Runnable, kotlin.coroutines.CoroutineContext)"
        at kotlinx.coroutines.selects.SelectBuilderImpl.onTimeout(Select.kt:651)
        at kotlinx.coroutines.flow.FlowKt__DelayKt$debounceInternal$1.invokeSuspend(Delay.kt:235)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.selects.SelectBuilderImpl.resumeWith(Select.kt:300)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
        at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:349)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:27)
        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)

Probably it is related to debounce()

viewModelScope.launch {
            searchQueryChannel.consumeAsFlow()
                    .debounce(200)
                    .collect {
                        filterSelectableList.postValue(it)
                    }
        }

These errors are due to mismatched versions of various coroutines modules.
Please ensure that kotlinx-coroutines-android and kotlinx-coroutines-core have the same version in your project.

You can do it using isForce or strictly in your gradle build:

// Note: kts syntax
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") {
    version {
        strictly("1.4.2")
    }
}

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android") {
    version {
        strictly("1.4.2")
    }
}

Also, filed #2494 to give a better diagnostics for misconfigured projects.

@qwwdfsad closed with the comment to use strict versions.

For completeness can you also give a guideline for the android platform? Should one use the coroutines-core or coroutines-android variant of the library?
The documentation suggests coroutines-core should suffice: _Don鈥檛 use kotlinx library artifact names with suffixes -common or -native. Instead, use the library root artifact name, which in the example above is kotlinx-coroutines-core_. I assumed that also means to not use -android? But coroutines-core crashes on withTimeoutOrNull on the android platform. Thanks!

kotlinx-coroutines-core is a multiplatform library (JVM, common, Native, JS), but with recent additions to multiplatform plugin you may forget about various variants and use it as is in common source set.

kotlinx-coroutines-android is not a multiplatform variant. It's a standalone JVM library that contains various utilities for Android development, e.g. Dispatchers.Main implementation. Typically, you should include it if you are working with Android. And then strict version should be used to avoid version mismatch of kotlinx-coroutines-core and kotlinx-coroutines-android

Was this page helpful?
0 / 5 - 0 ratings

Related issues

petersamokhin picture petersamokhin  路  3Comments

mariusstaicu picture mariusstaicu  路  3Comments

Pitel picture Pitel  路  3Comments

mhernand40 picture mhernand40  路  3Comments

Leftwitch picture Leftwitch  路  3Comments