I am trying to abort a transaction by throwing an exception throw ("Exception ==> Deliberate exit"); or by returning an error future return Future.error("Exception => Deliberate exit"); but the plugin spitting out another exception. The correct exception is reflected as a DoTransaction failed exception in java (see output below) but flutter throws the following exception PlatformException(Error performing transaction, Every document read in a transaction must also be written., null). I know flutter is throwing this exception because the remainder of the code is not executed where I would have written to the read document. Whether I have written to a read document should not matter after I have aborted. The transaction must fail and return my explicit exception/ or exception message.
Maybe I have missed something and this is not the proper way to abort a transaction (and return a message), I would be delighted to be shown the proper way. Thank you.
Code
try {
String profileId =
profilesCollectionRef(accountId: accountId).document().documentID;
final res = await Firestore.instance.runTransaction((tx) async {
DocumentSnapshot accountSnapshot =
await accountDocumentRef(accountId: accountId).get();
DocumentSnapshot userNameSnapshot =
await tx.get(userNamesCollectionRef.document(params.username));
if (accountSnapshot.exists) {
throw ("Exception ==> Deliberate exit");
//return Future.error("Exception => Deliberate exit");
if (userNameSnapshot.exists) {
throw ("Username now Taken");
}
...
await tx.set(
userNamesCollectionRef.document(params.username),
<String, dynamic>{
"profileId": profileId,
"dateCreated": FieldValue.serverTimestamp()
});
});
} catch (e,s) {
print("$e === > $s");
return Future.error(e,s);
}
Output
E/CloudFirestorePlugin(16362): java.lang.Exception: DoTransaction failed: Exception ==> Deliberate exit
E/CloudFirestorePlugin(16362): java.util.concurrent.ExecutionException: java.lang.Exception: DoTransaction failed: Exception ==> Deliberate exit
E/CloudFirestorePlugin(16362): at com.google.android.gms.tasks.Tasks.zzb(Unknown Source:61)
E/CloudFirestorePlugin(16362): at com.google.android.gms.tasks.Tasks.await(Unknown Source:33)
E/CloudFirestorePlugin(16362): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$4.apply(CloudFirestorePlugin.java:527)
E/CloudFirestorePlugin(16362): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$4.apply(CloudFirestorePlugin.java:479)
E/CloudFirestorePlugin(16362): at com.google.firebase.firestore.FirebaseFirestore.lambda$runTransaction$0(com.google.firebase:firebase-firestore@@21.3.0:301)
E/CloudFirestorePlugin(16362): at com.google.firebase.firestore.FirebaseFirestore$$Lambda$5.call(Unknown Source:6)
E/CloudFirestorePlugin(16362): at com.google.android.gms.tasks.zzv.run(Unknown Source:2)
E/CloudFirestorePlugin(16362): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/CloudFirestorePlugin(16362): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/CloudFirestorePlugin(16362): at java.lang.Thread.run(Thread.java:764)
E/CloudFirestorePlugin(16362): Caused by: java.lang.Exception: DoTransaction failed: Exception ==> Deliberate exit
E/CloudFirestorePlugin(16362): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$4$1$1.error(CloudFirestorePlugin.java:509)
E/CloudFirestorePlugin(16362): at io.flutter.plugin.common.MethodChannel$IncomingResultHandler.reply(MethodChannel.java:205)
E/CloudFirestorePlugin(16362): at io.flutter.embedding.engine.dart.DartMessenger.handlePlatformMessageResponse(DartMessenger.java:103)
E/CloudFirestorePlugin(16362): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessageResponse(FlutterJNI.java:642)
E/CloudFirestorePlugin(16362): at android.os.MessageQueue.nativePollOnce(Native Method)
E/CloudFirestorePlugin(16362): at android.os.MessageQueue.next(MessageQueue.java:326)
E/CloudFirestorePlugin(16362): at android.os.Looper.loop(Looper.java:181)
E/CloudFirestorePlugin(16362): at android.app.ActivityThread.main(ActivityThread.java:7050)
E/CloudFirestorePlugin(16362): at java.lang.reflect.Method.invoke(Native Method)
E/CloudFirestorePlugin(16362): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
E/CloudFirestorePlugin(16362): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
I/flutter (16362): PlatformException(Error performing transaction, Every document read in a transaction must also be written., null) === > #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:569:7)
I/flutter (16362): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
I/flutter (16362): <asynchronous suspension>
I/flutter (16362): #2 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:329:12)
I/flutter (16362): #3 MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:356:48)
I/flutter (16362): #4 MethodChannelFirestore.runTransaction (package:cloud_firestore_platform_interface/src/method_channel/method_channel_firestore.dart:123:10)
I/flutter (16362): #5 Firestore.runTransaction (package:cloud_firestore/src/firestore.dart:85:22)
I/flutter (16362): #6 ProfileRepo.createProfile (package:tsigira_app/data/repository/v1/profile_repo.dart:33:44)
I/flutter (16362): #7 CreateProfileUseCase._createAdditionalProfile (package:tsigira_app/domain/usecases/profile/create_profile_usecase.dart:54:25)
I/flutter (16362): #8 CreateProfileUse
Hi @tapsey
can you please provide your flutter doctor -v and flutter run --verbose?
Also, to better address the issue, would be helpful if you could post a minimal code sample to reproduce the problem
Thank you
This is fixed as part of #2582 (when it lands):

Required an overhaul of the transaction flow so it can't be backwards patched easily.
Hey this has been fixed as part of #2582 / #2913 - pending release.
Most helpful comment
This is fixed as part of #2582 (when it lands):
Required an overhaul of the transaction flow so it can't be backwards patched easily.