firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.71k stars 3.97k forks source link

🐛 [cloud_firestore] Flutter WhereNotIn with orderBy crashes the app #4906

Closed awaik closed 3 years ago

awaik commented 3 years ago

Bug report

If we make the request FireCollections.projects.where('userId', whereNotIn: mainUser.blockedUsersIds).orderBy('date', descending: true).get();

it crashes the app. I tried to user try - catch - it doesn't show anything.

If we change whereNotIn to whereIn - everything works as expected. So, it is clearly the bug with the whereNotIn statement.

Steps to reproduce

Steps to reproduce the behavior:

Just usewhereNotIn with orderBy with any data.

Expected behavior

Should work and not crash the app.


Additional context

Add any other context about the problem here.


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 1.22.6, on macOS 11.1 20C69 darwin-x64, locale en-RU) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.2) ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 12.1) [!] Android Studio ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. [!] VS Code (version 1.52.1) ✗ Flutter extension not installed; install from https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter [✓] Connected device (1 available) ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand ``` Dart SDK 2.10.5 Flutter SDK 1.22.6 popcrn 1.0.51 dependencies: - auto_size_text 2.1.0 [flutter] - better_player 0.0.48 [flutter cupertino_icons wakelock pedantic meta flutter_widget_from_html_core flutter_hls_parser visibility_detector path_provider] - cached_network_image 2.3.3 [flutter flutter_cache_manager octo_image] - cloud_firestore 0.14.4 [flutter meta quiver firebase_core firebase_core_platform_interface cloud_firestore_platform_interface cloud_firestore_web] - crypto 2.1.5 [collection convert typed_data] - cupertino_icons 1.0.0 - dots_indicator 1.2.0 [flutter] - file_picker 2.1.5+1 [flutter flutter_web_plugins flutter_plugin_android_lifecycle plugin_platform_interface] - firebase_auth 0.18.4+1 [meta firebase_core firebase_core_platform_interface firebase_auth_platform_interface firebase_auth_web flutter] - firebase_core 0.5.3 [firebase_core_platform_interface flutter quiver meta firebase_core_web] - firebase_dynamic_links 0.6.3 [flutter firebase_core] - firebase_messaging 7.0.3 [meta flutter firebase_core] - firebase_storage 4.0.1 [flutter firebase_core] - flushbar 1.10.4 [flutter] - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] - flutter_app_badger 1.1.2 [flutter] - flutter_google_places 0.2.6 [flutter rxdart google_maps_webservice http] - flutter_keyboard_size 0.1.2+2 [flutter provider] - flutter_staggered_grid_view 0.3.3 [flutter] - flutter_svg 0.19.1 [flutter meta path_drawing vector_math xml] - flutter_swipe_action_cell 1.2.2 [flutter] - geoflutterfire 2.2.1 [flutter cloud_firestore rxdart] - get 3.16.0 [flutter] - google_maps_webservice 0.0.18 [http meta] - google_sign_in 4.5.5 [google_sign_in_platform_interface flutter meta google_sign_in_web] - hive 1.4.4+1 [meta crypto] - hive_flutter 0.3.1 [flutter hive path_provider path] - http 0.12.2 [http_parser path pedantic] - image 2.1.19 [archive xml meta] - json_annotation 3.1.0 - like_button 1.0.4 [flutter] - liquid_swipe 1.5.0 [flutter provider] - modal_progress_hud 0.1.3 [flutter] - package_info 0.4.3+2 [flutter] - photo_view 0.10.3 [flutter] - sign_in_with_apple 2.5.4 [meta flutter] - skeleton_text 1.0.0 [flutter] - snapping_sheet 2.0.2 [flutter] - sqflite 1.3.2+2 [flutter sqflite_common path] - supercharged 1.11.1 [supercharged_dart flutter] - syncfusion_flutter_sliders 18.3.53-beta [flutter intl syncfusion_flutter_core] - video_compress 2.1.1 [flutter] - visibility_detector 0.1.5 [flutter] dev dependencies: - build_runner 1.10.3 [args async build build_config build_daemon build_resolvers build_runner_core code_builder collection crypto dart_style glob graphs http_multi_server io js logging meta mime path pedantic pool pub_semver pubspec_parse shelf shelf_web_socket stack_trace stream_transform timing watcher web_socket_channel yaml] - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data] - hive_generator 0.8.1 [build source_gen hive analyzer dartx] - json_serializable 3.5.0 [analyzer build build_config json_annotation meta path source_gen] transitive dependencies: - _fe_analyzer_shared 11.0.0 [meta] - analyzer 0.40.4 [_fe_analyzer_shared args charcode cli_util collection convert crypto glob meta package_config path pub_semver source_span watcher yaml] - archive 2.0.13 [crypto args path] - args 1.6.0 - async 2.5.0-nullsafety.1 [collection] - boolean_selector 2.1.0-nullsafety.1 [source_span string_scanner] - build 1.5.0 [analyzer async convert crypto logging meta path glob] - build_config 0.4.2 [checked_yaml json_annotation meta path pubspec_parse yaml] - build_daemon 2.1.4 [built_collection built_value http_multi_server logging pedantic path pool shelf shelf_web_socket stream_transform watcher web_socket_channel] - build_resolvers 1.4.2 [analyzer build crypto graphs logging meta path package_config pool pub_semver] - build_runner_core 6.0.3 [async build build_config build_resolvers collection convert crypto glob graphs json_annotation logging meta path package_config pedantic pool timing watcher yaml] - built_collection 4.3.2 [collection quiver] - built_value 7.1.0 [built_collection collection fixnum quiver] - characters 1.1.0-nullsafety.3 - charcode 1.2.0-nullsafety.1 - checked_yaml 1.0.2 [json_annotation source_span yaml] - cli_util 0.2.0 [path] - clock 1.1.0-nullsafety.1 - cloud_firestore_platform_interface 2.2.1 [flutter meta collection firebase_core plugin_platform_interface] - cloud_firestore_web 0.2.1+2 [flutter flutter_web_plugins http_parser meta firebase_core firebase_core_web cloud_firestore_platform_interface js] - code_builder 3.5.0 [built_collection built_value collection matcher meta] - collection 1.15.0-nullsafety.3 - convert 2.1.1 [charcode typed_data] - csslib 0.16.2 [source_span] - dart_style 1.3.8 [analyzer args path source_span] - dartx 0.5.0 [collection path crypto characters time meta] - fake_async 1.2.0-nullsafety.1 [clock collection] - ffi 0.1.3 - file 5.2.1 [intl meta path] - firebase_auth_platform_interface 2.1.4 [flutter meta firebase_core plugin_platform_interface] - firebase_auth_web 0.3.2+3 [flutter flutter_web_plugins meta http_parser intl firebase_core firebase_core_web firebase_auth_platform_interface js] - firebase_core_platform_interface 2.1.0 [flutter meta plugin_platform_interface quiver] - firebase_core_web 0.2.1+1 [firebase_core_platform_interface flutter flutter_web_plugins meta js] - fixnum 0.10.11 - flutter_blurhash 0.5.0 [flutter meta] - flutter_cache_manager 2.0.0 [flutter path_provider uuid http path sqflite pedantic clock file rxdart] - flutter_hls_parser 1.0.0 [flutter collection meta quiver] - flutter_plugin_android_lifecycle 1.0.11 [flutter] - flutter_web_plugins 0.0.0 [flutter characters collection meta typed_data vector_math] - flutter_widget_from_html_core 0.5.1+4 [flutter html] - glob 1.2.0 [async collection node_io path pedantic string_scanner] - google_sign_in_platform_interface 1.1.2 [flutter meta quiver] - google_sign_in_web 0.9.2 [google_sign_in_platform_interface flutter flutter_web_plugins meta js] - graphs 0.2.0 - html 0.14.0+4 [csslib source_span] - http_multi_server 2.2.0 [async] - http_parser 3.1.4 [charcode collection source_span string_scanner typed_data] - import_js_library 1.0.2 [flutter html flutter_web_plugins js] - intl 0.16.1 [path] - io 0.3.4 [charcode meta path string_scanner] - js 0.6.2 - logging 0.11.4 - matcher 0.12.10-nullsafety.1 [stack_trace] - meta 1.3.0-nullsafety.3 - mime 0.9.7 - nested 0.0.4 [flutter] - node_interop 1.1.1 [js] - node_io 1.1.1 [node_interop path] - octo_image 0.3.0 [flutter flutter_blurhash] - package_config 1.9.3 [path charcode] - path 1.8.0-nullsafety.1 - path_drawing 0.4.1+1 [vector_math meta path_parsing flutter] - path_parsing 0.1.4 [vector_math meta] - path_provider 1.6.27 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows] - path_provider_linux 0.0.1+2 [path xdg_directories path_provider_platform_interface flutter] - path_provider_macos 0.0.4+4 [flutter] - path_provider_platform_interface 1.0.3 [flutter meta platform plugin_platform_interface] - path_provider_windows 0.0.4+1 [path_provider_platform_interface meta path flutter ffi win32] - pedantic 1.9.2 [meta] - petitparser 3.1.0 [meta] - platform 2.2.1 - plugin_platform_interface 1.0.3 [meta] - pool 1.4.0 [async stack_trace] - process 3.0.13 [file intl meta path platform] - provider 4.3.2+2 [flutter nested collection] - pub_semver 1.4.4 [collection] - pubspec_parse 0.1.5 [checked_yaml json_annotation pub_semver yaml] - quiver 2.1.3 [matcher meta] - rxdart 0.24.1 - shelf 0.7.9 [async collection http_parser path stack_trace stream_channel] - shelf_web_socket 0.2.3 [shelf web_socket_channel stream_channel] - sky_engine 0.0.99 - source_gen 0.9.7+1 [analyzer async build dart_style glob meta path pedantic source_span] - source_span 1.8.0-nullsafety.2 [charcode collection path term_glyph] - sqflite_common 1.0.3 [synchronized path meta] - stack_trace 1.10.0-nullsafety.1 [path] - stream_channel 2.1.0-nullsafety.1 [async] - stream_transform 1.2.0 - string_scanner 1.1.0-nullsafety.1 [charcode source_span] - supercharged_dart 1.3.1 - syncfusion_flutter_core 18.3.53 [flutter pedantic] - synchronized 2.2.0+2 - term_glyph 1.2.0-nullsafety.1 - test_api 0.2.19-nullsafety.2 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher] - time 1.3.0 - timing 0.1.1+2 [json_annotation] - typed_data 1.3.0-nullsafety.3 [collection] - uuid 2.2.2 [crypto convert] - vector_math 2.1.0-nullsafety.3 - wakelock 0.2.1+1 [flutter meta wakelock_platform_interface wakelock_web] - wakelock_platform_interface 0.1.0+1 [flutter meta] - wakelock_web 0.1.0+3 [flutter flutter_web_plugins import_js_library js wakelock_platform_interface] - watcher 0.9.7+15 [async path pedantic] - web_socket_channel 1.1.0 [async crypto stream_channel] - win32 1.7.3 [ffi] - xdg_directories 0.1.2 [meta path process] - xml 4.5.1 [collection convert meta petitparser] - yaml 2.2.1 [charcode collection string_scanner source_span] ```

markusaksli-nc commented 3 years ago

Hi @awaik Could you please provide the error logs for the crash? Thank you

Ehesp commented 3 years ago

Could you show the code please on how you're error trapping?

Based on this: FireCollections.projects.where('userId', whereNotIn: mainUser.blockedUsersIds).orderBy('date', descending: true).get() I don't think that's a valid query.

If you have an inequality filter (whereNotIn) against the userId field, you need to also have the first orderBy as userId as well.

awaik commented 3 years ago

Hey guys, here is the link to how is the app crashing https://youtu.be/h8mgQGHJx8g

The error that I got:

Click To Expand ``` An error occurred while parsing query arguments, this is most likely an error with this SDK. ( 0 CoreFoundation 0x00007fff2043a126 __exceptionPreprocess + 242 1 libobjc.A.dylib 0x00007fff20177f78 objc_exception_throw + 48 2 Runner 0x000000010dd6baea _ZN8firebase9firestore4util16ObjcThrowHandlerENS1_13ExceptionTypeEPKcS4_iRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE + 554 3 Runner 0x000000010dd6b265 _ZN8firebase9firestore4util5ThrowENS1_13ExceptionTypeEPKcS4_iRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE + 53 4 Runner 0x000000010dffc165 _ZN8firebase9firestore4util20ThrowInvalidArgumentIJNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEES9_S9_EEEvPKcDpRKT_ + 85 5 Runner 0x000000010dffbd87 _ZNK8firebase9firestore3api5Query20ValidateOrderByFieldERKNS0_5model9FieldPathES6_ + 119 6 Runner 0x000000010dffb696 _ZNK8firebase9firestore3api5Que Lost connection to device. ```

@Ehesp Sorry, I don't understand - what do you mean by an inequality filter (whereNotIn) against the userId field

You can see on the video, that app works and crashes when I just add this filter. I can provide additional info, just didn't clearly understand what is wrong?

PS If I just change whereNotIn to whereIn - everything works fine. So, I guess, the reason is not in the inequality filter.

markusaksli-nc commented 3 years ago

@Ehesp There was an issue about this before as well https://github.com/FirebaseExtended/flutterfire/issues/4729

Should it really fatally crash though?

@awaik whereNotIn is an inequality filter whereas whereIn is an equality filter. The faulty query should still be the cause and you can get around it by having userId be the first orderBy.

Something like

FireCollections.projects.where('userId', whereNotIn: mainUser.blockedUsersIds).orderBy('userId').orderBy('date', descending: true).get();
awaik commented 3 years ago

@markusaksli-nc Thank you! You mean, that I have to use this request: res = await FireCollections.projects.where('userId', whereNotIn: mainUser.blockedUsersIds).orderBy('userId').orderBy('date', descending: true).get();

Yes, you are right, this works. BUT - I got the list sorted by userId - not by the date. Sorted by date only within one user projects. in case we have thousands of users it is not a decision.

markusaksli-nc commented 3 years ago

For now, this is likely the only way to get around the crash. You can order the list locally once you have the result.

Ehesp commented 3 years ago

@awaik I need to check whether it's even possible to do what you want with Firestore, the best way would be to boot up a quick HTML scratch pad with the JS SDKs are try the query there.

It shouldn't be crashing on native, but that error message suggests the query isn't possible anyway, so it'd be thrown in Dart land regardless.

awaik commented 3 years ago

For now, this is likely the only way to get around the crash. You can order the list locally once you have the result.

For now, the workaround is to get all records ordered by field and after, exclude records, that you don't need. Otherwise you get randomly sorted results with excluded records. The code of workaround:

res = await FireCollections.projects.orderBy('date', descending: true).get();
if (res.docs.isNotEmpty) projects = res.docs.map((e) => ProjectModel.fromDocument(e)).toList();
      projects.removeWhere((e) => mainUser.blockedUsersIds.contains(e.userId));

But, of course, this is a bad approach - we pay for requests, we do work on the user's phones. It would be nice to have a workable WhereNotIn filter.

nzackoya commented 3 years ago

This is completely unacceptable!!! With so many limitations and issues, this is a steal of time and money!!!!!!!!!!!!!!!!!!!!!!!!!! Even without ordering the WhereNotIn simply crashing the app. `==================================================================================================== An error occurred while parsing query arguments, this is most likely an error with this SDK. ( 0 CoreFoundation 0x00000001989659ec F3021642-E3C0-33F8-9911-DD303A6056D0 + 1157612 1 libobjc.A.dylib 0x00000001accebb54 objc_exception_throw + 56 2 FirebaseFirestore 0x0000000106059e70 _ZN8firebase9firestore4util16ObjcThrowHandlerENS1_13ExceptionTypeEPKcS4_iRKNSt3112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE + 464 3 FirebaseFirestore 0x0000000106059394 _ZN8firebase9firestore4util5ThrowENS1_13ExceptionTypeEPKcS4_iRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE + 68 4 FirebaseFirestore 0x000000010633124c _ZN8firebase9firestore4util20ThrowInvalidArgumentIJNSt3112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEES9EEEvPKcDpRKT + 80 5 FirebaseFirestore 0x0000000106330ab0 _ZNK8firebase9firestore3api5Query17ValidateNewFilterERKNS0_4core6FilterE + 700 6 FirebaseFirestore 0x000000010632fff0 _ZNK8firebase9firestore3api5Query6FilterENS0_5model9FieldPathENS0_4core6Filter8OperatorENS3_10FieldValueERKNSt318functionIFNS9_12basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEEvEEE + 644 7 FirebaseFirestore 0x0000000106151f90 -[FIRQuery queryWithFilterOperator:path:value:] + 316 8 FirebaseFirestore 0x000000010614ed5c -[FIRQuery queryWhereFieldPath:arrayContains:] + 140 9 Runner 0x0000000105305c64 -[FLTFirebaseFirestoreReader FIRQuery] + 1800 10 Runner 0x0000000105304e60 -[FLTFirebaseFirestoreReader readValueOfType:] + 1628 11 Flutter 0x0000000109f66dd4 -[FlutterStandardReader readValueOfType:] + 768 12 Runner 0x0000000105304f4c -[FLTFirebaseFirestoreReader readValueOfType:] + 1864 13 Flutter 0x0000000109f681f8 -[FlutterStandardMethodCodec decodeMethodCall:] + 84 14 Flutter 0x0000000109f65028 __45-[FlutterMethodChannel setMethodCallHandler:]_block_invoke + 44 15 Flutter 0x0000000109c78da8 _ZN7flutter15PlatformViewIOS21HandlePlatformMessageEN3fml6RefPtrINS_15PlatformMessageEEE + 504 16 Flutter 0x0000000109f7f5a0 _ZNSt3110function6funcIZN7flutter5Shell29OnEngineHandlePlatformMessageEN3fml6RefPtrINS2_15PlatformMessageEEEE4$_38NS_9allocatorIS8_EEFvvEEclEv + 108 17 Flutter 0x0000000109f1981c _ZN3fml15MessageLoopImpl10FlushTasksENS_9FlushTypeE + 1456 18 Flutter 0x0000000109f1c024 _ZN3fml17MessageLoopDarwin11OnTimerFireEP16_CFRunLoopTimerPS0 + 32 19 CoreFoundation 0x00000001988e63e0 F3021642-E3C0-33F8-9911-DD303A6056D0 + 635872 20 CoreFoundation 0x00000001988e5fe4 F3021642-E3C0-33F8-9911-DD303A6056D0 + 634852 21 CoreFoundation 0x00000001988e54c4 F3021642-E3C0-33F8-9911-DD303A6056D0 + 632004 22 CoreFoundation 0x00000001988df850 F3021642-E3C0-33F8-9911-DD303A6056D0 + 608336 23 CoreFoundation 0x00000001988deba0 CFRunLoopRunSpecific + 572 24 GraphicsServices 0x00000001af647598 GSEventRunModal + 160 25 UIKitCore 0x000000019b1d02f4 CC6E5AC7-8248-35F6-8B42-2E25C93DCF0A + 11723508 26 UIKitCore 0x000000019b1d5874 UIApplicationMain + 164 27 Runner 0x0000000104e1c7f4 main + 128 28 libdyld.dylib 0x00000001985bd568 0B475C78-3C12-3121-B7F8-2B95B83DAF44 + 5480 ) -[NSNull getDocumentsWithSource:completion:]: unrecognized selector sent to instance 0x1e93a1ee0 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull getDocumentsWithSource:completion:]: unrecognized selector sent to instance 0x1e93a1ee0' First throw call stack: (0x1989659d8 0x1accebb54 0x198875bbc 0x19896801c 0x198969f8c 0x105303aa8 0x105300bec 0x109f65070 0x109c78da8 0x109f7f5a0 0x109f1981c 0x109f1c024 0x1988e63e0 0x1988e5fe4 0x1988e54c4 0x1988df850 0x1988deba0 0x1af647598 0x19b1d02f4 0x19b1d5874 0x104e1c7f4 0x1985bd568) libc++abi.dylib: terminating with uncaught exception of type NSException

abdullah432 commented 3 years ago

@markusaksli-nc Thank you! You mean, that I have to use this request: res = await FireCollections.projects.where('userId', whereNotIn: mainUser.blockedUsersIds).orderBy('userId').orderBy('date', descending: true).get();

Yes, you are right, this works. BUT - I got the list sorted by userId - not by the date. Sorted by date only within one user projects. in case we have thousands of users it is not a decision.

      return db
          .collection('users')
          .where('blockeduserlist',
              whereNotIn: ['8VUG23Iv9XgDUNz5UNe4oIC3YMW2'])
          .where('numberofstories', isGreaterThan: 0)
          .orderBy('numberofstories')
          .snapshots()
          .map((snapshot) => snapshot.docs
              .map((doc) => CurrentUser.fromSnapshot(doc))
              .toList());

I have the same error and same case but with two where condition, the app is crashing. I checked orderBy with both 'numberofstories' and 'blockeduserlist' but both not working.

russellwheatley commented 3 years ago

This isn't a bug, this is expected behaviour. If you use an inequality filter (such as whereNotIn), the very next orderBy sort has to be on the same field. Therefore, if you use a whereNotIn on the field id, you ought to orderBy on the field id. I will update the plugin with another assert() to capture this error with a better message.