androidandroid-jetpack-composeillegalstateexception

What does "pending composition has not been applied" exception mean and how can it be avoided?


I have a working application, but sometimes, for reasons unknown to me, the application crashes with this message:

java.lang.IllegalStateException: pending composition has not been applied

I can't find information anywhere about the occurrence of this exception, and I also don't understand how it can be avoided.

Edit #1: After some research and testing, I found out that this exception is thrown when I quickly switch between tabs in BottomNavigation (tabs contain LazyColumn)


Solution

  • Since I don't have enough reputation to write a comment I will write it here. Maybe it helps you

    I got a same error today. And if I started debugging and I was putting lot of logging rows into my code to understand what exactly causes this issue. And I figured it out what for me caused this error. There was actual problem in my code that threw exception (array index out of bounds), but it seems that somewhere recomposition catches this actual error and throws more generic error.

    Simplified my code looked like this

    val items = myViewModel.items.collectAsState().value
    val focusRequesters = myViewModel.focusRequesters.collectAsState().value
    LazyColumn() {
        items(items = items) { item ->
            // When I added new item then I got error in this line, 
            // because I forgot to add new focusRequester when I was adding new item. 
            // so it was actually array index out of bounds error
            val focusRequester = focusRequesters[item.position]
            ...
            // Code to show item
        }
        item {
             AddItemButton(myViewModel)
        }
    }
    

    And actual error that it show me in the log was this generic error.

    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.courtesy.test, PID: 27394
        java.lang.IllegalStateException: pending composition has not been applied
            at androidx.compose.runtime.CompositionImpl.drainPendingModificationsForCompositionLocked(Composition.kt:530)
            at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:567)
            at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:811)
            at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3583)
            at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:503)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:408)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:383)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:374)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:363)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:648)
            at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:316)
            at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:243)
            at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
            at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1.placeChildren(SubcomposeLayout.kt:527)
            at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:980)
            at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:965)
            at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2063)
            at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:112)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:78)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:52)
            at androidx.compose.ui.node.LayoutNode.layoutChildren$ui_release(LayoutNode.kt:965)
            at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:950)
            at androidx.compose.ui.node.InnerPlaceable.placeAt-f8xVGno(InnerPlaceable.kt:78)
            at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
            at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.placeOuterWrapper-f8xVGno(OuterMeasurablePlaceable.kt:158)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.access$placeOuterWrapper-f8xVGno(OuterMeasurablePlaceable.kt:28)
            at androidx.compose.ui.node.OuterMeasurablePlaceable$placeAt$1.invoke(OuterMeasurablePlaceable.kt:146)
            at androidx.compose.ui.node.OuterMeasurablePlaceable$placeAt$1.invoke(OuterMeasurablePlaceable.kt:145)
            at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2063)
            at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:112)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:78)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutModifierSnapshotReads$ui_release(OwnerSnapshotObserver.kt:59)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.placeAt-f8xVGno(OuterMeasurablePlaceable.kt:145)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.replace(OuterMeasurablePlaceable.kt:170)
            at androidx.compose.ui.node.LayoutNode.replace$ui_release(LayoutNode.kt:838)
            at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:262)
            at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:36)
            at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:201)
    E/AndroidRuntime:     at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:773)
            at android.view.View.measure(View.java:25466)
            at androidx.compose.ui.platform.AbstractComposeView.internalOnMeasure$ui_release(ComposeView.android.kt:298)
            at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:285)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
            at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
            at com.android.internal.policy.DecorView.onMeasure(DecorView.java:747)
            at android.view.View.measure(View.java:25466)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3397)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2228)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2486)
            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)
    

    So at least for me this error was thrown when actual error happened during recomposition. Of course it would be nice if it would show me the actual error instead of this generic error.