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.69k stars 3.97k forks source link

🐛 [Realtime database] Attaching listeners throws exception when using arrays in Firebase #11829

Closed raccoonsplease closed 11 months ago

raccoonsplease commented 11 months ago

Bug report

I've been trying to read data from an RTDB. The DB consists of two large branches: devices and measurements.

Here is a visual representation of what I'm seeing on Firebase web UI:

devices --003 ----latest-measurement:"22f03cc35dadd863441de318048e2f72" ----time-of-registration:"2023-10-18 11:13:36 GMT+02:00" ----uid:"2023-10-18 11:13:36 GMT+02:00" measurements --22f03cc35dadd863441de318048e2f72 ----entries ------0Z735MQkjyRK93X7Iar5656VpX12 --------2 ----------1 ------------date:"Wed Oct 25 14:32:49 GMT+02:00 2023" ------------device:"132" ------------taskchild:"62" ------------user:"2"

Reading data from the devices branch works as intended. Reading from the measurements branch though, always throws an expection: [2023-11-03T13:50:57.587Z] @firebase/database: Error: Expected a value of type 'String', but got one of type 'Null' dart-sdk/lib/_internal/js_dev_runtime/private/ddcruntime/errors.dart 294:49 throw dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 127:3 castError dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 742:12 cast dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 674:17 as dart-sdk/lib/_internal/js_shared/lib/js_util_patch.dart 77:5 getProperty packages/firebase_database_web/src/utils/exception.dart 10:25 convertFirebaseDatabaseException packages/firebase_database_web/src/interop/database.dart 367:33 dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 574:37 _checkAndCall dart-sdk/lib/_internal/js_dev_runtime/private/ddcruntime/operations.dart 579:39 dcall https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:157987 onCancel https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:168888 https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:19285 exceptionGuard https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:142768 eventListRaise https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:142494 eventQueueRaiseQueuedEventsMatchingPredicate https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:142234 eventQueueRaiseEventsForChangedPath https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:145000 onComplete https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:51515 https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:55415 onDataMessage https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:39963 onDataMessage https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:39896 onPrimaryMessageReceived https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:38209 onMessage https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:33747 appendFrame_ https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:34299 handleIncomingFrame https://www.gstatic.com/firebasejs/10.3.1/firebase-database.js 1:32954 onmessage

After searching for a solution for a while, I found this StackOverflow post.

I suspect the Realtime Database plugin has issues with null values created by Firebase array coercion, potentially explaining the exception. Here is a snippet of the JSON export, supporting my theory:

{ "devices": { "dev": { "latest-measurement": "22f03cc35dadd863441de318048e2f72", "time-of-registration": "2023-10-18 11:13:36 GMT+02:00", "uid": "wPCJd6NUgCTS0V30kb4wcC8Vx8G2" } }, "measurements": { "22f03cc35dadd863441de318048e2f72": { "entries": { "0Z735MQkjyRK93X7Iar5656VpX12": { "2": [ null, { "date": "Wed Oct 25 14:32:49 GMT+02:00 2023", "device": "132", "taskchild": 62, "user": 2 }, { "date": "Wed Oct 25 15:02:49 GMT+02:00 2023", "device": "132", "taskchild": 62, "user": 2 } ] } } } } }

As far as I'm aware I have read all the relevant open issues on the tracker, any related posts on Stack Overflow and the documentation. My apologies if I have missed any obvious solutions.

Steps to reproduce

  1. Post two objects to the Firebase Realtime Database with an integer as a key, starting at 0 or 1.
  2. Attach an onValue (or any) listener to the root element or any child that itself has a descendant with array coercion.
  3. Run the Flutter app
  4. The exception appears

Expected behavior

I would expect the DataSnapShot to include the array-coerced data as an object, like the Firebase web UI displays the data.

Sample project

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:firebase_database/firebase_database.dart';

[..]

class _MainAppState() extends State<MainApp>{
    _MainAppState(){
        FirebaseDatabase database = FirebaseDatabase.instance;
        DatabaseReference databaseReference = database.ref();

        // Exception is thrown when the listener tries to read data
        databaseReference.child("measurements").onChildAdded.listen((event) {
            print("test");
        });
    }
}

Flutter doctor

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.13.9, on Microsoft Windows [Version 10.0.19045.3570], locale en-BE) [√] Windows Version (Installed version of Windows is version 10 or higher) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) X cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. X Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/windows#android-setup for more details. [√] Chrome - develop for the web [X] Visual Studio - develop Windows apps X Visual Studio not installed; this is necessary to develop Windows apps. Download at https://visualstudio.microsoft.com/downloads/. Please install the "Desktop development with C++" workload, including all of its default components [√] Android Studio (version 2022.2) [√] VS Code (version 1.83.1) [√] Connected device (3 available) [√] Network resources ! Doctor found issues in 2 categories. ```

Flutter dependencies

Click To Expand ``` Dart SDK 3.1.5 Flutter SDK 3.13.9 wlm_visualization 0.1.0 dependencies: - data_table_2 2.5.8 [flutter async] - firebase_core 2.21.0 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_database 10.3.3 [firebase_core firebase_core_platform_interface firebase_database_platform_interface firebase_database_web flutter] - fl_chart 0.64.0 [equatable flutter] - flutter 0.0.0 [characters collection material_color_utilities meta vector_math web sky_engine] - intl 0.18.1 [clock meta path] dev dependencies: - flutter_lints 2.0.3 [lints] - flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math async boolean_selector characters collection material_color_utilities meta source_span stream_channel string_scanner term_glyph web] transitive dependencies: - _flutterfire_internals 1.3.11 [collection firebase_core firebase_core_platform_interface flutter meta] - async 2.11.0 [collection meta] - boolean_selector 2.1.1 [source_span string_scanner] - characters 1.3.0 - clock 1.1.1 - collection 1.17.2 - equatable 2.0.5 [collection meta] - fake_async 1.3.1 [clock collection] - firebase_core_platform_interface 5.0.0 [collection flutter flutter_test meta plugin_platform_interface] - firebase_core_web 2.8.1 [firebase_core_platform_interface flutter flutter_web_plugins js meta] - firebase_database_platform_interface 0.2.5+11 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface] - firebase_database_web 0.2.3+11 [firebase_core firebase_core_web firebase_database_platform_interface flutter flutter_web_plugins js] - flutter_web_plugins 0.0.0 [flutter characters collection material_color_utilities meta vector_math web] - js 0.6.7 [meta] - lints 2.1.1 - matcher 0.12.16 [async meta stack_trace term_glyph test_api] - material_color_utilities 0.5.0 [collection] - meta 1.9.1 - path 1.8.3 - plugin_platform_interface 2.1.6 [meta] - sky_engine 0.0.99 - source_span 1.10.0 [collection path term_glyph] - stack_trace 1.11.0 [path] - stream_channel 2.1.1 [async] - string_scanner 1.2.0 [source_span] - term_glyph 1.2.1 - test_api 0.6.0 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph] - vector_math 2.1.4 - web 0.1.4-beta ```

raccoonsplease commented 11 months ago

I'm an idiot. The reason why the 'measurements' branch would always throw an error is because of the Firebase rules that would not allow a write on the locations where I tested.

It would be nice if the exception thrown would point in the direction of permissions issue rather than 'Expected String got null'.