Skip to content
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

java.lang.IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied #126

Open
sabotrev opened this issue Jan 6, 2025 · 2 comments

Comments

@sabotrev
Copy link

sabotrev commented Jan 6, 2025

We are seeing a growing crash after upgrading from 0.11.2 to 0.14.0. Unfortunately, the stack trace does not include any of my app's code, and we haven't been able to figure out how to reproduce the issue.

java.lang.IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied
    at androidx.compose.runtime.snapshots.SnapshotKt.readError(Snapshot.kt:2059)
    at androidx.compose.runtime.snapshots.SnapshotKt.current(Snapshot.kt:2402)
    at androidx.compose.runtime.DerivedSnapshotState.current(DerivedState.kt:167)
    at androidx.compose.runtime.DerivedSnapshotState$ResultRecord.readableHash(DerivedState.kt:142)
    at androidx.compose.runtime.DerivedSnapshotState$ResultRecord.isValid(DerivedState.kt:114)
    at androidx.compose.runtime.DerivedSnapshotState.currentRecord(DerivedState.kt:175)
    at androidx.compose.runtime.DerivedSnapshotState.getValue(DerivedState.kt:272)
    at me.saket.telephoto.subsamplingimage.RealSubSamplingImageState.getViewportTiles(RealSubSamplingImageState.kt:182)
    at me.saket.telephoto.subsamplingimage.RealSubSamplingImageState.access$getViewportTiles(RealSubSamplingImageState.kt:40)
    at me.saket.telephoto.subsamplingimage.RealSubSamplingImageState$LoadImageTilesEffect$2.invokeSuspend(RealSubSamplingImageState.kt:157)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
    at androidx.compose.ui.platform.AndroidUiDispatcher.access$setScheduledFrameDispatch$p(AndroidUiDispatcher.android.kt:41)
    at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
    at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:233)
    at android.app.ActivityThread.main(ActivityThread.java:8063)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)

I'll update here if I discover anything further, thanks!

@saket
Copy link
Owner

saket commented Jan 7, 2025

Oh boy, this is going to be challenging to investigate. I wonder if this is happening because the value of viewportTiles is backed by a state, and the values read on line 155 and 157 can differ in race conditions.

LaunchedEffect(imageCache, viewportTiles) {
imageCache.loadOrUnloadForTiles(
regions = viewportTiles.fastMapNotNull { if (it.isVisible) it.region else null }
)
}

I could change this to the following in an attempt to fix this:

val viewportTiles = this.viewportTiles
LaunchedEffect(imageCache, viewportTiles) {
  imageCache.loadOrUnloadForTiles(
    regions = viewportTiles.fastMapNotNull { if (it.isVisible) it.region else null }
  )
}

Thoughts? cc @rharter who I remember was investigating a similar crash last month and might have suggestions.

@SzyQ
Copy link

SzyQ commented Jan 15, 2025

I think the reason it worked on version 0.11.2 was the RealSubSamplingImageState had simple states, which were assigned after the calculation was ready.
Version 0.14.0 is using derivedStateOf more extensively, which I think are a bit buggy and hard to debug once they cause a crash. Most recently there was a fix for a nested derivedStateOf, where the changes correlate with the stacktrace we saw in the crashes here.
So once this fix is published, we will be ready to verify if it fixes the problem.

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

No branches or pull requests

3 participants