realm-kotlin icon indicating copy to clipboard operation
realm-kotlin copied to clipboard

[RLM_ERR_WRONG_TRANSACTION_STATE]: Not a read transaction - Not in our codebase

Open leowroth opened this issue 5 months ago • 5 comments

How frequently does the bug occur?

Sometimes

Description

We switched in our Android app from Java SDK to Kotlin, because we had issues with thread safety and the frozen architecture works better for us.

Now after the release, some of our users have a new crash, which doesn't happen in our code. Or at least it's not visible in the stacktrace. Can you give us a hint, how we can prevent or fix this? Or is this a bug, you'll have to fix in the SDK?

Stacktrace & log output

# Crashlytics - Stack trace
# Platform: android
# Version: 8.16.1 (577)

Fatal Exception: java.lang.IllegalStateException: [RLM_ERR_WRONG_TRANSACTION_STATE]: Not a read transaction
       at io.realm.kotlin.internal.interop.CoreErrorConverter.asThrowable(CoreErrorConverter.kt:47)
       at io.realm.kotlin.internal.interop.realmcJNI.realm_begin_write(realmcJNI.java)
       at io.realm.kotlin.internal.interop.realmc.realm_begin_write(realmc.java:462)
       at io.realm.kotlin.internal.interop.RealmInterop.realm_begin_write(RealmInterop.kt:393)
       at io.realm.kotlin.internal.WriteTransactionManager$DefaultImpls.beginTransaction(WriteTransactionManager.kt:28)
       at io.realm.kotlin.internal.SuspendableWriter$WriterRealm.beginTransaction(SuspendableWriter.kt:58)
       at io.realm.kotlin.internal.SuspendableWriter$write$2.invokeSuspend(SuspendableWriter.kt:123)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at java.lang.Thread.run(Thread.java:923)

FinalizerDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:442)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
       at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:273)
       at java.lang.Daemons$Daemon.run(Daemons.java:139)
       at java.lang.Thread.run(Thread.java:923)

com.mixpanel.android.AnalyticsWorker:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loop(Looper.java:206)
       at android.os.HandlerThread.run(HandlerThread.java:67)

TokenRefresher:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loop(Looper.java:206)
       at android.os.HandlerThread.run(HandlerThread.java:67)

Okio Watchdog:
       at sun.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2197)
       at okio.AsyncTimeout$Companion.awaitTimeout$okio(AsyncTimeout.kt:320)
       at okio.AsyncTimeout$Watchdog.run(AsyncTimeout.kt:186)

WM.task-2:
       at sun.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:190)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2067)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1092)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at java.lang.Thread.run(Thread.java:923)

Okio Watchdog:
       at java.lang.Object.wait(Object.java)
       at com.android.okhttp.okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:325)
       at com.android.okhttp.okio.AsyncTimeout.access$000(AsyncTimeout.java:42)
       at com.android.okhttp.okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:288)

Can you reproduce the bug?

No

Reproduction Steps

No response

Version

1.13.0

What Atlas App Services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

Android 8, 10, 11, 13

Build environment

Android Studio version: Hedgehog | 2023.1.1 Patch 2 Android Build Tools version: 24.0.8215888 Gradle version: 8.1.3

leowroth avatar Feb 05 '24 13:02 leowroth

@leowroth

Does it happen when the app is launched or during execution? And you have no write transactions in your app (I see beginTransaction) in the stack trace?

kneth avatar Feb 07 '24 14:02 kneth

Thanks for your questions, sadly I can't answer them. All I know is, what I posted here. We only see this crash on firebase and don't know how to reproduce, therefor we can't say when it's happening.

Not sure I understand your point about beginTransaction. We write new data via realm.writeBlocking{}

leowroth avatar Feb 08 '24 08:02 leowroth

doesn't happen in our code

If the transaction isn't happening in your code, I am wondering where it comes from. Does it happen only when the app launches (schema migrations will require a transaction - but hidden in the app's code)?

kneth avatar Feb 13 '24 16:02 kneth

This issue is crashing our app. Normally with crashes, I get a stack trace with information, where the last call (class + line of code) in our code was, that triggered the crash.

In this case we don't have that information. That's why I opened this issue. I want to understand how we can prevent this crash or at least, how we can make sure we get the full stack trace with information about what call triggered it.

And again, we don't know when it happens. This stack trace is from our crash analytics. So some unknown users got this crash and we don't know how to reproduce.

leowroth avatar Feb 20 '24 08:02 leowroth

Hi @leowroth. It seems like our internal writer realm is in an erroneous state, which should not happen. This could be the case if you are opening the same realm file multiple times with Realm.open and do not synchronize your writes between the two instances.

Alternatively it could be that you are hit by this issue where an exception in a write/writeBlocking could skip rolling back the transaction. The fix for that is yet not released, but is available in 1.13.1-SNAPSHOT, which can be used following these instructions

rorbech avatar Feb 22 '24 10:02 rorbech

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

github-actions[bot] avatar Apr 26 '24 00:04 github-actions[bot]