Skip to content

AbstractMethodError when use withTimeout #2307

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

Closed
francismariano opened this issue Oct 15, 2020 · 15 comments
Closed

AbstractMethodError when use withTimeout #2307

francismariano opened this issue Oct 15, 2020 · 15 comments

Comments

@francismariano
Copy link

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

@elizarov
Copy link
Contributor

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

@francismariano
Copy link
Author

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.

@sphrak
Copy link

sphrak commented Oct 17, 2020

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 🤷‍♂️. This is a plain android kotlin project and in coroutines 1.3.9 this exception was not thrown.

@d4rken
Copy link

d4rken commented Oct 18, 2020

Likely a version mismatch like in #1033

@mkotyk
Copy link

mkotyk commented Oct 28, 2020

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()

@lukas1
Copy link

lukas1 commented Oct 29, 2020

@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.

@mkotyk-godaddy
Copy link

That did the trick @lukas1. thanks for the solution! 🙇

@uburoiubu
Copy link

@elizarov, any clarifications for this issue?

@elizarov
Copy link
Contributor

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?

@ikurek
Copy link

ikurek commented Nov 30, 2020

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.

@suandplzop
Copy link

suandplzop commented Jan 8, 2021

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.

@isamotiuc
Copy link

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)
                    }
        }

@qwwdfsad
Copy link
Member

qwwdfsad commented Jan 25, 2021

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.

@aptly-io
Copy link

@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’t 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!

@qwwdfsad
Copy link
Member

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

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

No branches or pull requests