java.lang.IllegalStateException: Cannot create asynchronous query while in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310
See original GitHub issueGoal
Avoid crashes.
Expected Results
Crashes do not happen. Transactions completes successful without crashes. Also I want to know what kind of code can lead to this crash.
Actual Results
Error. StackTrace:
java.lang.IllegalStateException: Cannot create asynchronous query while in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310
at io.realm.internal.Collection.nativeStartListening(Native Method)
at io.realm.internal.Collection.addListener(Collection.java:490)
at io.realm.internal.Collection.addListener(Collection.java:497)
at ...
Steps & Code to Reproduce
I do not know how to reproduce it. I haven’t got anything helpful after searching all the issues and in stackoverflow.com. And I also searched the crash message Cannot create asynchronous query while in a write transaction in realm source code but found nothing. It’s not a new issue and I first found this crash about one month ago. I found some similar problems in I-OS Realm, but there is no information about the solution https://github.com/realm/realm-cocoa/issues/4539 https://github.com/realm/realm-cocoa/issues/4231 https://stackoverflow.com/questions/42012222/realm-why-are-notification-blocks-triggered-when-a-write-transaction-begins
Code Sample
I’ve read the doc and cannot find what’s wrong with my code. I know how to avoid common problems like nested transactions. But this one is killing me. Our application (en.techops.brief) uses several threads and asynchronous transactions. The problem periodically occurs in different parts of the code, here are two cases and a stacktrace:
Case 1: Useq StackTrace: https://gist.github.com/andrey7mel/e121d0e856bb20d536d970a314bdf3b0 Realm 3.3.0
05-25 18:25:02.659 15486-15486/ru.techops.brief.debug E/REALM_JNI: jni: ThrowingException 8, Cannot create asynchronous query while in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310, .
05-25 18:25:02.659 15486-15486/ru.techops.brief.debug E/REALM_JNI: Exception has been thrown: Cannot create asynchronous query while in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310
05-25 18:25:02.666 15486-15486/ru.techops.brief.debug E/ChatPresenter.l()[351]: Error while getting chat events:
java.lang.IllegalStateException: Cannot create asynchronous query while in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310
at io.realm.internal.Collection.nativeStartListening(Native Method)
at io.realm.internal.Collection.addListener(Collection.java:490)
at io.realm.internal.Collection.addListener(Collection.java:497)
at io.realm.RealmResults.addChangeListener(RealmResults.java:171)
at io.realm.rx.RealmObservableFactory$6.call(RealmObservableFactory.java:153)
at io.realm.rx.RealmObservableFactory$6.call(RealmObservableFactory.java:137)
at rx.Observable.unsafeSubscribe(Observable.java:10256)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:45)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10256)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10256)
at rx.internal.operators.OperatorSwitch$SwitchSubscriber.onNext(OperatorSwitch.java:155)
at rx.internal.operators.OperatorSwitch$SwitchSubscriber.onNext(OperatorSwitch.java:77)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:77)
at rx.internal.operators.OperatorCast$CastSubscriber.onNext(OperatorCast.java:69)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.onNext(OnSubscribeFilter.java:76)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.onNext(OnSubscribeFilter.java:76)
at io.realm.rx.RealmObservableFactory$10$1.onChange(RealmObservableFactory.java:293)
at io.realm.rx.RealmObservableFactory$10$1.onChange(RealmObservableFactory.java:289)
at io.realm.ProxyState$RealmChangeListenerWrapper.onChange(ProxyState.java:46)
at io.realm.internal.OsObject$ObjectObserverPair.onChange(OsObject.java:69)
at io.realm.internal.OsObject$Callback.onCalled(OsObject.java:88)
at io.realm.internal.OsObject$Callback.onCalled(OsObject.java:73)
at io.realm.internal.ObserverPairList.foreach(ObserverPairList.java:108)
at io.realm.internal.OsObject.notifyChangeListeners(OsObject.java:236)
at io.realm.internal.SharedRealm.nativeBeginTransaction(Native Method)
at io.realm.internal.SharedRealm.beginTransaction(SharedRealm.java:262)
at io.realm.BaseRealm.beginTransaction(BaseRealm.java:348)
at io.realm.BaseRealm.beginTransaction(BaseRealm.java:343)
at io.realm.Realm.beginTransaction(Realm.java:131)
at io.realm.Realm.executeTransaction(Realm.java:1441)
at ru.techops.brief.model.database.DataBase.executeTransaction(DataBase.java:1720)
at ru.techops.brief.model.database.DataBase.lambda$null$1(DataBase.java:149)
at ru.techops.brief.model.database.DataBase$$Lambda$160.call(Unknown Source)
at rx.internal.operators.OnSubscribeCreate.call(OnSubscribeCreate.java:72)
at rx.internal.operators.OnSubscribeCreate.call(OnSubscribeCreate.java:32)
at rx.Observable.unsafeSubscribe(Observable.java:10256)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:224)
at rx.android.schedulers.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
Code transaction:
// ru.techops.brief.model.database.DataBase.lambda$null$1(DataBase.java:149)
saveUseqSubject
.onBackpressureLatest()
.concatMap(useq -> Observable.create(emitter -> {
executeTransaction(realm -> {
Useq useqObj = realm.where(Useq.class).findFirst();
if (useqObj == null) {
useqObj = new Useq();
}
useqObj.setUseq(useq);
realm.insertOrUpdate(useqObj);
emitter.onNext(useq);
});
}, Emitter.BackpressureMode.BUFFER))
.subscribe(useq1 -> Timber.v("Saved to database Useq=" + useq1),
e -> Timber.e(e, "Error while saving useq to Realm"));
//ru.techops.brief.model.database.DataBase.executeTransaction(DataBase.java:1720)
private void executeTransaction(Realm.Transaction transaction) {
try (Realm realm = getRealm()) {
realm.executeTransaction(transaction);
}
}
Case 2: SaveEvents Stacktrace: https://gist.github.com/andrey7mel/10e6b54e741d99d08bd2f6174cece094 Realm 3.1.4
Non-fatal Exception: java.lang.IllegalStateException: Cannot create asynchronous query while in a write transaction in /home/cc/repo/realm/release/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 310
at io.realm.internal.Collection.nativeStartListening(Collection.java)
at io.realm.internal.Collection.addListener(Collection.java:490)
at io.realm.internal.Collection.addListener(Collection.java:497)
at io.realm.RealmResults.addChangeListener(RealmResults.java:136)
at io.realm.rx.RealmObservableFactory$6.call(RealmObservableFactory.java:153)
at io.realm.rx.RealmObservableFactory$6.call(RealmObservableFactory.java:137)
at rx.Observable.unsafeSubscribe(Observable.java:10346)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:45)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10346)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10346)
at rx.internal.operators.OperatorSwitch$SwitchSubscriber.onNext(OperatorSwitch.java:155)
at rx.internal.operators.OperatorSwitch$SwitchSubscriber.onNext(OperatorSwitch.java:77)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:77)
at rx.internal.operators.OperatorCast$CastSubscriber.onNext(OperatorCast.java:69)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.onNext(OnSubscribeFilter.java:76)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.onNext(OnSubscribeFilter.java:76)
at io.realm.rx.RealmObservableFactory$10$1.onChange(RealmObservableFactory.java:293)
at io.realm.rx.RealmObservableFactory$10$1.onChange(RealmObservableFactory.java:289)
at io.realm.ProxyState$RealmChangeListenerWrapper.onChange(ProxyState.java:46)
at io.realm.internal.OsObject$ObjectObserverPair.onChange(OsObject.java:67)
at io.realm.internal.OsObject$Callback.onCalled(OsObject.java:86)
at io.realm.internal.OsObject$Callback.onCalled(OsObject.java:71)
at io.realm.internal.ObserverPairList.foreach(ObserverPairList.java:108)
at io.realm.internal.OsObject.notifyChangeListeners(OsObject.java:149)
at io.realm.internal.SharedRealm.nativeBeginTransaction(SharedRealm.java)
at io.realm.internal.SharedRealm.beginTransaction(SharedRealm.java:246)
at io.realm.BaseRealm.beginTransaction(BaseRealm.java:309)
at io.realm.Realm.beginTransaction(Realm.java:128)
at io.realm.Realm.executeTransaction(Realm.java:1408)
at ru.techops.brief.model.database.DataBase.executeTransaction(DataBase.java:1729)
at ru.techops.brief.model.database.DataBase.saveEventsSync(DataBase.java:636)
at ru.techops.brief.model.Model.lambda$saveEventsSync$85(Model.java:888)
at ru.techops.brief.model.Model$$Lambda$70.call(Unknown Source)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:69)
at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
at rx.internal.producers.ProducerArbiter.setProducer(ProducerArbiter.java:126)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.setProducer(OnSubscribeConcatMap.java:329)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
at rx.Observable.unsafeSubscribe(Observable.java:10346)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10346)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.innerCompleted(OnSubscribeConcatMap.java:209)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.onCompleted(OnSubscribeConcatMap.java:345)
at rx.observers.SerializedObserver.onCompleted(SerializedObserver.java:176)
at rx.observers.SerializedSubscriber.onCompleted(SerializedSubscriber.java:64)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:246)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.innerCompleted(OnSubscribeConcatMap.java:209)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.onCompleted(OnSubscribeConcatMap.java:345)
at rx.observers.SerializedObserver.onCompleted(SerializedObserver.java:176)
at rx.observers.SerializedSubscriber.onCompleted(SerializedSubscriber.java:64)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:246)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.innerCompleted(OnSubscribeConcatMap.java:209)
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.onCompleted(OnSubscribeConcatMap.java:345)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onCompleted(OperatorMerge.java:281)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onCompleted(OperatorOnErrorResumeNextViaFunction.java:101)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.checkTerminated(OperatorObserveOn.java:281)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:216)
at rx.android.schedulers.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5896)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:948)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:809)
Code:
// ru.techops.brief.model.Model.lambda$saveEventsSync$85(Model.java:888)
public Completable saveEventsSync(List<WsUpdateEventNew> updates) {
List<Event> events = new ArrayList<>();
for (WsUpdateEventNew update : updates) {
events.add(update.getEvent());
}
return Observable.from(events)
.concatMap(event -> {
Observable<Object> res = Observable.empty();
User sender = dataBase.getUserSyncFromRealm(event.getSenderId());
if (sender == null) {
res = res.concatWith(getUserInfoFromServer(event.getSenderId()));
}
Peer fwdSenderPeer = event.getFwdSenderPeer();
if (fwdSenderPeer != null) {
User fwdSender = dataBase.getUserSyncFromRealm(fwdSenderPeer.getPeerId());
if (fwdSender == null) {
res = res.concatWith(getUserInfoFromServer(fwdSenderPeer.getPeerId()));
}
}
Peer peer = event.getPeer();
Const.NotifyMode notifyMode = dataBase.getPeerNotifyMode(peer);
if (notifyMode == Const.NotifyMode.NOTIFY_UNKNOWN) {
switch (peer.getType()) {
case PeerType.USER:
res = res.concatWith(getUserInfoFromServer(event.getPeer().getPeerId()));
break;
case PeerType.GROUP:
res = res.concatWith(getGroupInfoFromServer(event.getPeer().getPeerId()));
break;
}
}
if (event.getReplyToId() != 0) {
res = res.concatWith(loadEventIfNeed(event.getPeer(), event.getReplyToId()).ignoreElements());
}
return res;
})
.concatWith(Observable.just(events)
.map(e -> {
// (Model:888)
dataBase.saveEventsSync(e);
return e;
}))
.toCompletable();
}
//ru.techops.brief.model.database.DataBase.saveEventsSync(DataBase.java:636)
@WorkerThread
public void saveEventsSync(List<Event> events) {
executeTransaction(realm -> {
for (Event event : events) {
saveEventToRealm(event, realm);
}
});
}
// ru.techops.brief.model.database.DataBase.executeTransaction(DataBase.java:1729)
private void executeTransaction(Realm.Transaction transaction) {
try (Realm realm = getRealm()) {
realm.executeTransaction(transaction);
}
}
Version of Realm and tooling
Realm version(s): 3.1.4 - 3.3.0
Realm sync feature enabled: no
Android Studio version: 2.3.2
Which Android version and device: Android 5 - 6 - 7, many devices
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (6 by maintainers)
@cmelchior due to the nature of how Object Store running the queries, even
findAll()
will be put into background thread if it is possible. That means callingfindAll().addChangeListener()
inside a transaction is not allowed as well.@cmelchior