Describe the bug
I have some StreamBuilders that listen for Firestore streams events, when the widget receives a didUpdateWidget callback the cloud_firestore plugin crashes:
E/flutter (25570): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: PlatformException(error, Attempt to invoke interface method 'void com.google.firebase.firestore.ListenerRegistration.remove()' on a null object reference, null)
E/flutter (25570): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:572:7)
E/flutter (25570): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:161:18)
E/flutter (25570): <asynchronous suspension>
E/flutter (25570): #2 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:334:12)
E/flutter (25570): #3 MethodChannelQuery.snapshots.<anonymous closure> (package:cloud_firestore_platform_interface/src/method_channel/method_channel_query.dart:145:48)
E/flutter (25570): #4 _runGuarded (dart:async/stream_controller.dart:847:24)
E/flutter (25570): #5 _BroadcastStreamController._callOnCancel (dart:async/broadcast_stream_controller.dart:358:5)
E/flutter (25570): #6 _BroadcastStreamController._recordCancel (dart:async/broadcast_stream_controller.dart:229:9)
E/flutter (25570): #7 _ControllerSubscription._onCancel (dart:async/stream_controller.dart:883:24)
E/flutter (25570): #8 _BufferingStreamSubscription._cancel (dart:async/stream_impl.dart:264:21)
E/flutter (25570): #9 _BufferingStreamSubscription.cancel (dart:async/stream_impl.dart:210:7)
E/flutter (25570): #10 _ForwardingStreamSubscription._onCancel (dart:async/stream_pipe.dart:149:27)
E/flutter (25570): #11 _BufferingStreamSubscription._cancel (dart:async/stream_impl.dart:264:21)
E/flutter (25570): #12 _BufferingStreamSubscription.cancel (dart:async/stream_impl.dart:210:7)
E/flutter (25570): #13 _ForwardingStreamSubscription._onCancel (dart:async/stream_pipe.dart:149:27)
E/flutter (25570): #14 _BufferingStreamSubscription._cancel (dart:async/stream_impl.dart:264:21)
E/flutter (25570): #15 _BufferingStreamSubscription.cancel (dart:async/stream_impl.dart:210:7)
E/flutter (25570): #16 _FlatMapStreamSink.onCancel.<anonymous closure> (package:rxdart/src/transformers/flat_map.dart:52:56)
E/flutter (25570): #17 MappedListIterable.elementAt (dart:_internal/iterable.dart:417:31)
E/flutter (25570): #18 ListIterator.moveNext (dart:_internal/iterable.dart:343:26)
E/flutter (25570): #19 Future.wait (dart:async/future.dart:402:26)
E/flutter (25570): #20 _FlatMapStreamSink.onCancel (package:rxdart/src/transformers/flat_map.dart:52:14)
E/flutter (25570): #21 forwardStream.<anonymous closure> (package:rxdart/src/utils/forwarding_stream.dart:43:51)
E/flutter (25570): #22 _runGuarded (dart:async/stream_controller.dart:847:24)
E/flutter (25570): #23 _BroadcastStreamController._callOnCancel (dart:async/broadcast_stream_controller.dart:358:5)
E/flutter (25570): #24 _BroadcastStreamController._recordCancel (dart:async/broadcast_stream_controller.dart:229:9)
E/flutter (25570): #25 _ControllerSubscription._onCancel (dart:async/stream_controller.dart:883:24)
E/flutter (25570): #26 _BufferingStreamSubscription._cancel (dart:async/stream_impl.dart:264:21)
E/flutter (25570): #27 _BufferingStreamSubscription.cancel (dart:async/stream_impl.dart:210:7)
E/flutter (25570): #28 _StreamBuilderBaseState._unsubscribe (package:flutter/src/widgets/async.dart:158:21)
E/flutter (25570): #29 _StreamBuilderBaseState.didUpdateWidget (package:flutter/src/widgets/async.dart:121:9)
E/flutter (25570): #30 StatefulElement.update (package:flutter/src/widgets/framework.dart:4734:58)
E/flutter (25570): #31 Element.updateChild (package:flutter/src/widgets/framework.dart:3245:15)
E/flutter (25570): #32 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4571:16)
E/flutter (25570): #33 Element.rebuild (package:flutter/src/widgets/framework.dart:4262:5)
E/flutter (25570): #34 StatelessElement.update (package:flutter/src/widgets/framework.dart:4627:5)
E/flutter (25570): #35 Element.updateChild (package:flutter/src/widgets/framework.dart:3245:15)
E/flutter (25570): #36 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5881:14)
E/flutter (25570): #37 Element.updateChild (package:flutter/src/widgets/framework.dart:3245:15)
E/flutter (25570): #38 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5881:14)
E/flutter (25570): #39 Element.updateChild (package:flutter/src/widgets/framework.dart:3245:15)
E/flutter (25570): #40 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4571:16)
E/flutter (25570): #41 Element.rebuild (package:flutter/src/widgets/framework.dart:4262:5)
E/flutter (25570): #42 StatelessElement.update (package:flutter/src/widgets/framework.dart:4627:5)
E/flutter (25570): #43 Element.updateChild (package:flutter/src/
It may be caused by another error:
E/flutter (25570): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Invalid argument: Instance of 'DocumentReference'
E/flutter (25570): #0 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:395:7)
E/flutter (25570): #1 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #2 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:385:9)
E/flutter (25570): #3 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #4 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:385:9)
E/flutter (25570): #5 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #6 StandardMessageCodec.writeValue.<anonymous closure> (package:flutter/src/services/message_codecs.dart:392:9)
E/flutter (25570): #7 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (25570): #8 MapView.forEach (dart:collection/maps.dart:345:10)
E/flutter (25570): #9 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:390:13)
E/flutter (25570): #10 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #11 StandardMessageCodec.writeValue.<anonymous closure> (package:flutter/src/services/message_codecs.dart:392:9)
E/flutter (25570): #12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (25570): #13 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:390:13)
E/flutter (25570): #14 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #15 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:98:7)
E/flutter (25570): #16 StandardMessageCodec.writeValue.<anonymous closure> (package:flutter/src/services/message_codecs.dart:392:9)
E/flutter (25570): #17 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (25570): #18 StandardMessageCodec.writeValue (package:flutter/src/services/message_codecs.dart:390:13)
E/flutter (25570): #19 FirestoreMessageCodec.writeValue (package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart:114:13)
E/flutter (25570): #20 StandardMethodCodec.encodeMethodCall (package:flutter/src/services/message_codecs.dart:527:18)
E/flutter (25570): #21 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:153:13)
E/flutter (25570): #22 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:334:12)
E/flutter (25570): #23 MethodChannelQuery.snapshots.<anonymous closure> (package:cloud_firestore_platform_interface/src/method_channel/method_channel_query.dart:133:48)
E/flutter (25570): #24 _runGuarded (dart:async/stream_controller.dart:847:24)
E/flutter (25570): #25 _BroadcastStreamController._subscribe (dart:async/broadcast_stream_controller.dart:213:7)
E/flutter (25570): #26 _ControllerStream._createSubscription (dart:async/stream_controller.dart:860:19)
E/flutter (25570): #27 _StreamImpl.listen (dart:async/stream_impl.dart:493:9)
E/flutter (25570): #28 new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:118:10)
E/flutter (25570): #29 _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:88:16)
E/flutter (25570): #30 _ForwardingStream.listen (dart:async/stream_pipe.dart:83:12)
E/flutter (25570): #31 new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:118:10)
E/flutter (25570): #32 _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:88:16)
E/flutter (25570): #33 _ForwardingStream.listen (dart:async/stream_pipe.dart:83:12)
E/flutter (25570): #34 _FlatMapStreamSink.add (package:rxdart/src/transformers/flat_map.dart:22:33)
E/flutter (25570): #35 forwardStream.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:rxdart/src/utils/forwarding_stream.dart:34:49)
E/flutter (25570): #36 forwardStream.runCatching (package:rxdart/src/utils/forwarding_stream.dart:24:12)
E/flutter (25570): #37 forwardStream.<anonymous closure>.<anonymous closure> (package:rxdart/src/utils/forwarding_stream.dart:34:28)
E/flutter (25570): #38 _rootRun
To Reproduce
Using a complex Firestore stream (a query stream that is RxDart flatMapped into another query stream) with a StreamBuilder.
Expected behavior
The plugin shouldn't crash when it tries to remove a ListenerRegistration that doesn't exist (null).
Or it shouldn't try to remove it at all.
See listenerRegistrations.get(handle) that returns null at FlutterFirebaseFirestorePlugin.java:496.
Flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.20.2, on Mac OS X 10.15.6 19G73, locale it-IT)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.47.3)
[✓] Connected device (2 available)
• No issues found!
Looks like the plugin crashes when method_channel_query.dart:133 calls:
MethodChannelFirebaseFirestore.channel.invokeMethod<void>(
'Query#addSnapshotListener',
<String, dynamic>{
'query': this,
'handle': handle,
'firestore': firestore,
'includeMetadataChanges': includeMetadataChanges,
},
);
When query contains a DocumentReference as parameter:

I fear this might require an urgent fix...
Hi @thearaks
Can you please provide your pubpsec.yaml and a complete reproducible minimal code sample
Thank you
@TahaTesser found the error and a workaround.
Apparently you can't use a DocumentReference instance in queries since 0.14.0.
While in previous versions of the plugin this worked fine:
FirebaseFirestore.instance
.collection('projects')
.where('ownerRef', isEqualTo: FirebaseFirestore.instance.collection('users').doc(uid))
.where('deletedAt', isNull: true)
.snapshots();
Now causes this crash and needs to be replaced with a string representation of the DocumentReference:
FirebaseFirestore.instance
.collection('projects')
.where('ownerRef', isEqualTo: 'users/$uid')
.where('deletedAt', isNull: true)
.snapshots()
Is this the expected behavior or is it a regression?
pubspec.yaml for completeness:
name: test
description: The Test.
version: 0.1.1+1
environment:
sdk: ">=2.5.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
cupertino_icons: ^0.1.2
flutter_inappwebview: ^4.0.0+4
package_info: ^0.4.1
shared_preferences: ^0.5.8
provider: ^4.3.1
rxdart: ^0.24.1
tuple: ^1.0.3
email_validator: ^1.0.5
url_launcher: ^5.5.0
store_redirect: ^1.0.2
image_picker: ^0.6.7+4
notification_permissions: ^0.4.6
flutter_auth_buttons: ^0.9.0
google_sign_in: ^4.5.1
firebase_auth: ^0.18.0
firebase_messaging: ^7.0.0
firebase_analytics: ^6.0.0
firebase_crashlytics: ^0.1.4+1
firebase_remote_config: ^0.4.0
cloud_firestore: ^0.14.0
dependency_overrides:
flutter_svg: ^0.18.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
flutter_intl:
enabled: true
I'll pick this one up - this may be unintended regression.
I had to revert to cloud_firestore: ^0.13.7 because i need queries on DocumentReferences values and because the 0.14.0 version has a lot of problems keeping track of the stream controllers so when it tries to cancel streams or add data to a stream it crashes.
Thank you @Ehesp!
@thearaks Just to confirm, is the ownerRef key/value a Reference within the database?
because the 0.14.0 version has a lot of problems keeping track of the stream controllers so when it tries to cancel streams or add data to a stream it crashes.
Is this another issue?
@Ehesp yes, In the example i pasted above ownerRef is a Reference inside the database.
Unfortunately the workaround seems to have worked with some entities but not with others (?!) so I had to revert to the previous version.
Then, beside that, I fear there's another issue related to a mis-handling of the stream controllers so when the plugin tries to close a stream or tries to add data from Firestore to the stream it crashes with an NPE or with an error on an assert controller != null (see the first stacktrace i posted).
@thearaks On the first issue, I think this is a simple fix. On this line, this needs adding:
value = _CodecUtility.valueEncode(value);
Could you quickly add that locally and check it works? I'll get PR up, but I'm going to add some more tests around this at the same time.
@Ehesp I can confirm that your change solves the first issue with the DocumentReference!
Sweet 👍 I'll push up a fix.
Could you send over a simplified pseudo code of your Widget which includes the Stream? I assume the didUpdateWidget is because some native handler is triggering a removal of the native listeners.
@thearaks on the second issue, how fast are you updating your widget with the Stream in it? The only way I can see this happening is that:
Ok, found the second issue too! PR linked.
@Ehesp great!
Thank you very much for your fixes!
Release with a fix is now published. Latest versions can be seen here.
Thanks again for the bug report :)