Hi all :wave::skin-tone-3: Running into a hard to ...
# compose
t
Hi all 👋🏼 Running into a hard to repro crash that spouts
java.lang.IllegalStateException: Unsupported concurrent change during composition. A state object was modified by composition as well as being modified outside composition.
We don’t seem to be creating `mutableStateOf`s explicitly at all, much less modifying them on both sides of Composition boundaries…Any tips on where to start looking? Any help is much appreciated! 🙏🏼 More in 🧵
Compose version:
1.2.0
Compose Compiler version:
1.3.0
Full trace (this is all of the trace - the trace doesn’t actually point to the offending code 😞)
Copy code
java.lang.IllegalStateException: Unsupported concurrent change during composition. A state object was modified by composition as well as being modified outside composition.
at (Coroutine boundary.()
at androidx.compose.runtime.PausableMonotonicFrameClock.withFrameNanos(PausableMonotonicFrameClock.kt:63)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2.invokeSuspend(Recomposer.kt:454)
at androidx.compose.runtime.Recomposer$recompositionRunner$2$2.invokeSuspend(Recomposer.kt:745)
at androidx.compose.runtime.Recomposer$recompositionRunner$2.invokeSuspend(Recomposer.kt:744)
at androidx.compose.ui.platform.WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1.invokeSuspend(WindowRecomposer.android.kt:391)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@7eb0113, androidx.compose.ui.platform.MotionDurationScaleImpl@1156f50, CoroutineId(2420), "coroutine#2420":StandaloneCoroutine

{Cancelling}
@5eaf549, AndroidUiDispatcher@b3cde4e]
Caused by: java.lang.IllegalStateException: Unsupported concurrent change during composition. A state object was modified by composition as well as being modified outside composition.
at androidx.compose.runtime.Recomposer.applyAndCheck(Recomposer.kt:957)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1283)
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:970)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:727)
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)
r
It's a bit difficult to know what's causing that without any code 😢 I think this has happened to me once in the past, do you have some coroutine going on or modifying something in a sneaky way? If not*, I would try to set logs everywhere if it's easy to reproduce and remove code to verify that's the issue*
t
It’s a bit difficult to know what’s causing that without any code
I agree…the problem is I have no idea what the offending code may even be…so I have no idea what snippet to post…TL;DR - its a screen with a
TextField
and a dropdown menu with a
LazyColumn
- the state is coming from a
StateFlow
where
collectAsState()
is used.
I think this has happened to me once in the past,
Oh interesting! Do you happen to remember what the culprit was?
do you have some coroutine going on or modifying something in a sneaky way
The only thing we do is
rememberCoroutineScope()
to animate a `LazyListState`… which should be typical, I think
b
Tried updating to Compose 1.3? There were a couple of fixes that could be related
t
Upgrade failed because compileSdk 33 is required and we’re stuck at 32 :(
s
How come you’re stuck at 32? Are you sure you can’t update compileSdk to 33 and keep targetSdk to 32 to be able to test this out?
t
Oop, totally interchanged targetSdk and compileSdk in my head. Going to try out compileSdk 33 and hopefully Compose 1.3.1 and see if the issues still persist. Also trying out things like replacing
LazyColumn
with
Column
because of possible instability with
LazyColumn
🤞🏼
Oh no, still seeing the same with Compose 1.3.1 😞
s
It might be the case of some internal state update races with recompose, looking at the trace I see some
WindowRecomposer
things that are a bit suspicious Can you try to file a bug with a small repro?
a
I've hit a few of these, but right now I can't remember exactly where I set a breakpoint to find it (since the callstack of the exception doesn't help at all), I think maybe it was putting a breakpoint in Snapshot.kt / notifyWrite() and hitting that breakpoint many times but keep looking to see what thread its on until one thats not main thread hits. (hopefully its a deterministic issue) I think last time I ran into this I it was with a mutable map or mutable state list and it wouldn't let us update from another thread even though it was created outside of a compose context.
t
So the original ui was hosted in a Fragment inside a BottomSheetDialog Fragment (that sat inside a Fragment page of a ViewPager 😬) Interestingly enough the issue went away after launching the original ui in a separate Activity + Fragment (without a bottom sheet or ViewPager). Makes me think that the
WindowRecomposer
idea makes sense @shikasd. Might try to file a bug (although minimal repro might be hard to get)
169 Views