Status Update
Comments
jo...@google.com <jo...@google.com>
li...@tomtom.com <li...@tomtom.com> #2
After upgrading to kotlin 2.1.0 and bumping remaining dependencies, things seem to work as expected again. EDIT: My bad; was on the wrong branch. Those upgrades did NOT help.
jo...@google.com <jo...@google.com> #3
I think I managed to track it down further:
In my Child
composable, I'm actually hitting a TODO()
statement:
@Composable
fun Child(isLoading: Boolean, items: List<MyDataClass>) {
// ...
if (notYetSupported) {
TODO("This is not yet supported!")
}
// ...
}
It would seem that compose swallows this error and throws the above instead which is not very helpful.
li...@tomtom.com <li...@tomtom.com> #4
The "pending composition has not been applied" error generally means that composition continued despite something in the hierarchy previously throwing an exception. Here it looks like something is continuing a subcomposition unexpectedly, possibly a LazyList.
We should see if we can improve this error messaging. Can you send over a more complete example? The snippets here aren't fleshed out enough to reproduce this swallowing behavior.
li...@tomtom.com <li...@tomtom.com> #5
Triage notes: It feels like we're very close to having a repro case that we could run internally, but we don't know where the sub-composition is coming from.
Can you send over a more complete example?
Let's hold until we can get a stable repro case from the reporter. Could you send us a ZIP of the project that repros this issue? We'll close this out in a month if we don't get a response.
Bugjuggler: wait 1 month
jo...@google.com <jo...@google.com> #6
li...@google.com <li...@google.com> #7
This took me about an hour to extract but it reproduces the issue for me.
@file:SuppressLint("UnusedMaterialScaffoldPaddingParameter")
package com.example
import android.annotation.SuppressLint
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import kotlinx.coroutines.delay
class MyApp : Application()
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
// Scaffold is required!
Scaffold { _ ->
val a = remember { mutableStateOf(true) }
val b = remember { mutableStateOf(true) }
LaunchedEffect(Unit) {
a.value = false
delay(50)
b.value = false
}
AnimatedVisibility(visible = a.value) { Text("Hello World") }
if (!b.value) {
TODO()
}
}
}
}
}
}
li...@tomtom.com <li...@tomtom.com> #8
Thank you! I was able to reproduce locally. Will look into this. We may eventually dedupe to
One thing to note is that this is definitely related to a race condition. Device speed matters, and a slower device seems more likely to trigger this exception — My aging Pixel XL from 2016 reproduces this very consistently, unlike my local emulator which doesn't demonstrate this issue at all. We had suspected that coroutines were coming into play here, so a lot of pieces are starting to come together.
li...@google.com <li...@google.com>
li...@tomtom.com <li...@tomtom.com> #9
Correction: The emulator I was using had animations disabled. This seems to reproduce very consistently across devices.
It looks like our exception handling logic is try/catching Exception
instead of Throwable
. TODO() is breaking things because it throws a NotImplementedError
, which isn't caught by our error handler and doesn't cancel pending recompositions. We'll update our code to include Errors and generic Throwable classes. It's not immediately obvious if this will fix other occurrences of this exception since we don't have other reproduction cases.
li...@google.com <li...@google.com>
li...@google.com <li...@google.com> #10
Project: platform/frameworks/support
Branch: androidx-main
Author: Andrew Bailey <
Link:
Fix Throwables causing unapplied composition error
Expand for full commit details
Fix Throwables causing unapplied composition error
The error handling logic in the Recomposer was set up to catch
throwables that extended from Exception, which excluded Errors (like
NotImplementedError, error(""), StackOverflowError, etc.) and
user-defined exceptions that extend directly from Throwable. This CL
updates the relevant pathways to switch over all Throwables.
This resolves at least one pathway that leads to a "Pending composition
has not been applied." runtime error. It's not immediately clear if this
accounts for all of the reports since we only have one known
reproduction case right now.
Test: Manually run repro case in the linked bug
Fixes: b/382094412
Relnote: """
Fixes an issue where raising a throwable during composition that
does not extend from Exception may lead to a 'Pending composition
has not been applied' error.
"""
Change-Id: I356be5d99df41138be790275807544b2d717050c
Files:
- M
compose/runtime/runtime/api/current.txt
- M
compose/runtime/runtime/api/restricted_current.txt
- M
compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/LiveEditApiTests.kt
- M
compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/HotReloader.kt
- M
compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
- M
compose/runtime/runtime/src/nonEmulatorJvmTest/kotlin/androidx/compose/runtime/LiveEditTests.kt
Hash: 120c3f0cfa04436bd9afabea415a478e12458316
Date: Wed Jan 08 15:38:34 2025
li...@tomtom.com <li...@tomtom.com> #11
Can you repro this bug locally?
> We don't have reproduce steps locally for this. We will let you know if we can manage to reproduce it consistently locally.
Does this happen on a specific Screen of yours, or on some, many, all?
> We don't know which screen this happens. We do see this crash happen very frequently among our beta users.
We use builder.build() in all the getTemplate() methods, can builder.build() ever return null? Do we need to do null check there and return a special screen?
In our code, we have "getLifecycle().addObserver(this)" in all the screen constructors, like it is used in the sample apps, but, not doing removeObserver(this) anywhere. Could this be a problem? What is the best practice here? Is it necessary to do removeObserver? Perhaps in finalize()?
Are there any best practice on how the screen should be used that we perhaps missed?
Hope you have received the code Snippet I sent to N, if not, I can send to you directly.
Cheers!
li...@tomtom.com <li...@tomtom.com> #12
Template template = XXX.getTemplate();
if (template !=null) {
template.getClass()
} else {
Log.E(TAG, "template should not be null")
}
li...@tomtom.com <li...@tomtom.com> #13
li...@google.com <li...@google.com> #14
As per our offline conversation, this seems to be a race condition in the shutdown of both processes. I'll look into mitigating this in a future release
li...@google.com <li...@google.com>
ap...@google.com <ap...@google.com> #15
Branch: androidx-main
commit 076857f2f01e8e30f8186cad44ce22192438073a
Author: Rafael Lima <therafael@google.com>
Date: Thu Feb 25 23:28:48 2021
Improvements to shutdown scenarios
1. Do not send calls to app level callbacks if the app is not at least
in created state
2. Do not crash the app if the host is dead while trying to send an IPC
Follow up review will stop dispatching calls from template related
callbacks (i.e. onClick, etc)
Relnote: "Improvements to not dispatch calls to app if its lifecycle is
not at least in a created state"
Test: Unit tests
Bug:180530156
Bug:179800224
Bug:177921120
Bug:178516889
Change-Id: I8696503d1a9859411c4a52fa73d2852c8b3383d9
M car/app/app-testing/src/main/java/androidx/car/app/testing/TestAppManager.java
M car/app/app-testing/src/main/java/androidx/car/app/testing/TestCarContext.java
M car/app/app-testing/src/main/java/androidx/car/app/testing/navigation/TestNavigationManager.java
M car/app/app/src/main/java/androidx/car/app/AppManager.java
M car/app/app/src/main/java/androidx/car/app/CarAppService.java
M car/app/app/src/main/java/androidx/car/app/CarContext.java
M car/app/app/src/main/java/androidx/car/app/HostDispatcher.java
M car/app/app/src/main/java/androidx/car/app/ScreenManager.java
M car/app/app/src/main/java/androidx/car/app/model/OnCheckedChangeDelegateImpl.java
M car/app/app/src/main/java/androidx/car/app/model/OnClickDelegateImpl.java
M car/app/app/src/main/java/androidx/car/app/model/OnItemVisibilityChangedDelegateImpl.java
M car/app/app/src/main/java/androidx/car/app/model/OnSelectedDelegateImpl.java
M car/app/app/src/main/java/androidx/car/app/model/SearchCallbackDelegateImpl.java
M car/app/app/src/main/java/androidx/car/app/navigation/NavigationManager.java
M car/app/app/src/main/java/androidx/car/app/utils/LogTags.java
M car/app/app/src/main/java/androidx/car/app/utils/RemoteUtils.java
M car/app/app/src/test/java/androidx/car/app/AppManagerTest.java
M car/app/app/src/test/java/androidx/car/app/CarAppServiceTest.java
M car/app/app/src/test/java/androidx/car/app/CarContextTest.java
M car/app/app/src/test/java/androidx/car/app/HostDispatcherTest.java
M car/app/app/src/test/java/androidx/car/app/navigation/NavigationManagerTest.java
li...@google.com <li...@google.com> #16
We have fixed this issue now and it will be available in a following release
Description
1.0.0-beta.1
Devices/Android versions reproduced on:
- Samsung Galaxy. Pixel 3. A wide range of devices. with Android 9, Android 10 and Android 11.
Android Auto version reproduced on:
- 5.9.604633-release
If this is a bug in the library, we would appreciate if you could attach, if possible:
- Sample project to trigger the issue.
In the code, getTemplate() could return null sometimes. It is not clear in the documentation if we could return null for this function.
- A screen record or screenshots showing the issue (if UI related).
- A bug report. See attached log.txt.