koin icon indicating copy to clipboard operation
koin copied to clipboard

java.lang.IllegalStateException: Compose Runtime internal error after updating to Koin 3.2.0

Open racka98 opened this issue 2 years ago • 12 comments

Description After updating to Koin 3.2.0 from 3.1.6 my Compose app crashes with

java.lang.IllegalStateException: Compose Runtime internal error. Unexpected or incorrect use of the Compose internal runtime API (Start/end imbalance).

Tried with 3.1.5 and 3.1.6 both work fine. Updating to 3.2.0 causes this crash. I believe this is a bug in Koin.

Also came across a similar issue on Google's issue tracker: https://issuetracker.google.com/issues/233126425 The author also appears to be using Koin.

Expected behavior App should not crash

Version koin-core version 3.2.0 koin-android version 3.2.0 koin-androidx-compose version 3.2.0

racka98 avatar Jun 05 '22 14:06 racka98

+1 same here, needed to downgrade to 3.1.6 to get it working again.

TheNephilim88 avatar Jun 05 '22 20:06 TheNephilim88

any solutions?

Secack avatar Jun 18 '22 15:06 Secack

any more stack trace or way to reproduce?

arnaudgiuliani avatar Jun 27 '22 14:06 arnaudgiuliani

politely bumping this issue.

danielRi avatar Jun 27 '22 17:06 danielRi

Stacktrace:

Java.lang.IllegalStateException: Compose Runtime internal error. Unexpected or incorrect use of the Compose internal runtime API (Start/end imbalance). Please report to Google or use https://goo.gle/compose-feedback
at androidx.compose.runtime.ComposerKt.composeRuntimeError(Composer.kt:3466)
at androidx.compose.runtime.ComposerImpl.finalizeCompose(Composer.kt:3550)
at androidx.compose.runtime.ComposerImpl.endRoot(Composer.kt:1237)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2588)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2547)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:620)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:786)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:105)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:456)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:425)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:997)
at android.view.Choreographer.doCallbacks(Choreographer.java:797)
at android.view.Choreographer.doFrame(Choreographer.java:728)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:984)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@de5e03, StandaloneCoroutine{Cancelling}@8a52180, AndroidUiDispatcher@78473b9]

nachtien avatar Jun 28 '22 11:06 nachtien

I also got the crash but noticed if I move the line out of the setContent method the error seems to have vanished:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Moved the following line to here...
        val homePageViewModel: HomePageViewModel by viewModel()
        setContent {
            // ...Because here it caused the crash (commented out)
            // val homePageViewModel: HomePageViewModel by viewModel()
            val navController = rememberNavController()
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                ) {
                    NavHost(navController = navController, startDestination = "home") {
                        composable("home") { HomePage(navController, homePageViewModel) }
                        composable("search") { SearchPage() }
                        /*...*/
                    }
                }
            }
        }
    }
}

Not sure why the error occurs if I inject the viewModel within the setContent function

danielRi avatar Jun 28 '22 16:06 danielRi

I also got the crash but noticed if I move the line out of the setContent method the error seems to have vanished:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Moved the following line to here...
        val homePageViewModel: HomePageViewModel by viewModel()
        setContent {
            // ...Because here it caused the crash (commented out)
            // val homePageViewModel: HomePageViewModel by viewModel()
            val navController = rememberNavController()
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                ) {
                    NavHost(navController = navController, startDestination = "home") {
                        composable("home") { HomePage(navController, homePageViewModel) }
                        composable("search") { SearchPage() }
                        /*...*/
                    }
                }
            }
        }
    }
}

Not sure why the error occurs if I inject the viewModel within the setContent function

It vanishes because you are no longer using the compose specific methods for ViewModel. The issue is specific to using the compose viewModel() method inside compose. Moving everything out of compose kind of defeats the purpose

racka98 avatar Jun 29 '22 05:06 racka98

@racka98 I think you should update your question or show your code to make it more clear for the developers.

danielRi avatar Jun 29 '22 08:06 danielRi

an update is needed regarding ViewModel API & Compose 👍

arnaudgiuliani avatar Jul 18 '22 06:07 arnaudgiuliani

I got the same

Version

koin_version = '3.2.0'

App Log

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: snipped ..., PID: 4643
    java.lang.IllegalStateException: Compose Runtime internal error. Unexpected or incorrect use of the Compose internal runtime API (Start/end imbalance). Please report to Google or use https://goo.gle/compose-feedback
        at androidx.compose.runtime.ComposerKt.composeRuntimeError(Composer.kt:4244)
        at androidx.compose.runtime.ComposerImpl.finalizeCompose(Composer.kt:4390)
        at androidx.compose.runtime.ComposerImpl.endRoot(Composer.kt:1390)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3208)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3148)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:739)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:876)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:107)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:485)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:454)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
        at android.view.Choreographer.doCallbacks(Choreographer.java:899)
        at android.view.Choreographer.doFrame(Choreographer.java:827)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
        at android.os.Handler.handleCallback(Handler.java:942)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
    	Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@2e7902e, androidx.compose.ui.platform.MotionDurationScaleImpl@c1a97cf, StandaloneCoroutine{Cancelling}@aade55c, AndroidUiDispatcher@914e065]

Snipped ... Koin Log

D/[Koin]: +- '{snipped ...}.features.calculators.standard.presentation.CalculatorViewModel'
D/[Koin]: | create instance for [Factory:'{snipped ...}.features.calculators.standard.presentation.CalculatorViewModel']
D/[Koin]: +- '{snipped ...}.features.settings.domain.usecases.GetSettings'
D/[Koin]: | create instance for [Singleton:'{snipped ...}.features.settings.domain.usecases.GetSettings']
D/[Koin]: +- '{snipped ...}.core.repository.SettingsRepository'
D/[Koin]: | create instance for [Singleton:'{snipped ...}.core.repository.SettingsRepositoryImpl',binds:{ snipped ... }.core
.repository.SettingsRepository]
D/[Koin]: +- 'androidx.datastore.core.DataStore'
D/[Koin]: | create instance for [Singleton:'androidx.datastore.core.DataStore']
D/[Koin]: +- 'android.content.Context'
D/[Koin]: | create instance for [Singleton:'android.app.Application',binds:android.content.Context,android.app.Application]
D/[Koin]: |- 'android.content.Context' in 0.2217 ms
D/[Koin]: |- 'androidx.datastore.core.DataStore' in 13.4381 ms
D/[Koin]: |- '{snipped ...}.core.repository.SettingsRepository' in 15.7899 ms
D/[Koin]: |- '{snipped ...}.features.settings.domain.usecases.GetSettings' in 16.9416 ms
D/[Koin]: |- '{snipped ...}.features.calculators.standard.presentation.CalculatorViewModel' in 47.5962 ms

Morons avatar Jul 24 '22 08:07 Morons

Edit: That was my mistake, the assignment should be without delegation: = instead of by. Leaving here as a reference

I got a similar error, in a super basic composable, it crashes/got fixed by adding/removing the line #5

#1 import org.koin.androidx.compose.viewModel
#2
#3 @Composable
#4 fun HomeScreen(modifier: Modifier = Modifier) {
#5    val viewModel: HomeViewModel by viewModel()
#6    HomeScreen(state = HomeState.Idle, modifier = modifier)
#7 }

IntelliJ CE 2022.2 RC Gradle: 7.4.2 Multimodule Multiplatform project ( Compose modules are plain Jvm + Android, not KMP ) Kotin: 1.7.10 Compose: 1.3.0-alpha01 Compose compiler: 1.3.0-beta01 (edit: just tried with rc01 as well, same) Koin: 3.2.0

java.lang.IllegalStateException: Compose Runtime internal error. Unexpected or incorrect use of the Compose internal runtime API (Start/end imbalance). Please report to Google or use https://goo.gle/compose-feedback
        at androidx.compose.runtime.ComposerKt.composeRuntimeError(Composer.kt:4244)
        at androidx.compose.runtime.ComposerImpl.finalizeCompose(Composer.kt:4390)
        at androidx.compose.runtime.ComposerImpl.endRoot(Composer.kt:1390)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3208)
        at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3119)
        at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:578)
        at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:811)
        at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:513)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
        at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1052)
        at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131)
        at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)
        at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:202)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
        at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1139)
        at android.view.View.dispatchAttachedToWindow(View.java:20479)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2417)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

fardavide avatar Jul 28 '22 14:07 fardavide

This might be a duplicate of #1347 and a possible workaround is to replace lazy viewModel with getViewModel

zeromod avatar Aug 01 '22 13:08 zeromod

Yep, seems something to do with Lazy. I'm currently investigating on it 👍

arnaudgiuliani avatar Sep 01 '22 16:09 arnaudgiuliani

The root cause is that we are now using closely the ViewModel API from Google and it doesn't support any kind of Lazy or ViewModelLazy retuned type in Compose 1.1+

Best is to use the eager API: koinViewModel() or even get()

I will deprecate with error lazy APIs of koin-androidx-compose in 3.2.1

arnaudgiuliani avatar Sep 06 '22 09:09 arnaudgiuliani