Skip to content

[cloud_firestore]: startAfterDocument does not correctly return an empty query snapshot #18233

@IVLIVS-III

Description

@IVLIVS-III

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Database

Which platforms are affected?

Web

Description

startAfterDocument does not correctly return an empty query snapshot.

When the base query only has a single document that matches all query filters, and when that document's snapshot is set as the startAfterDocument cursor, I expect an empty query snapshot to be returned.
This is exactly what happens on macOS.

However, on web, a non-empty query snapshot is returned, including the single document that was already set as the startAfterDocument cursor.

I encountered this issue while trying to load a collection in batches that could have had upwards of 500 documents, but had only a single document after multiple query filters were applied.

Reproducing the issue

  1. Create a new Firebase project.
  2. Enable Firestore (for debugging purposes in test mode).
  3. Clone the repo at https://github.com/IVLIVS-III/cloud_firestore_issue_18233.
  4. Open the Firebase project created in step 1 in the Google Cloud Console and create a cloud storage bucket in the same region as Firestore.
  5. Unzip the firestore export located in the repo at storage/export_firestore.zip.
  6. Upload the firestore export folder from step 5 to the cloud storage bucket created in step 4.
  7. Navigate to "Import/Export" in the Firestore section on the Google Cloud Console.
  8. Import the data uploaded in step 6.
  9. Run flutterfire configure and choose the project created in step 1.
  10. Run the app in debug mode on web.
  11. Click on "Load Collection". This will print an error in the console, prompting you to create an index.
  12. Follow the link provided by the error message to create the index. Wait until the index is created.
  13. Click on "Load Collection" again. This will result in the infinite loop.

I want to load the complete collection in batches with the while loop in lib/main.dart. The break on an empty query snapshot should end the loop in theory after the complete collection is loaded.
If the complete collection has either no documents at all or at least 2 documents, everything works fine.

However, if the complete collection only has a single document, then each iteration returns a query snapshot with exactly that single document.
This results in an infinite loop.

Firebase Core version

4.7.0

Flutter Version

3.41.6

Relevant Log Output

Flutter dependencies

Expand Flutter dependencies snippet
Dart SDK 3.11.4
Flutter SDK 3.41.6
cloud_firestore_issue_18233 1.0.0+1

dependencies:
- cloud_firestore 6.3.0 [cloud_firestore_platform_interface cloud_firestore_web collection firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 4.7.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine]

dev dependencies:
- flutter_lints 6.0.0 [lints]
- flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math leak_tracker_flutter_testing collection meta stream_channel]

transitive dependencies:
- _flutterfire_internals 1.3.69 [collection firebase_core firebase_core_platform_interface flutter meta]
- async 2.13.1 [collection meta]
- boolean_selector 2.1.2 [source_span string_scanner]
- characters 1.4.1
- clock 1.1.2
- cloud_firestore_platform_interface 7.2.0 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- cloud_firestore_web 5.3.0 [_flutterfire_internals cloud_firestore_platform_interface collection firebase_core firebase_core_web flutter flutter_web_plugins]
- collection 1.19.1
- fake_async 1.3.3 [clock collection]
- firebase_core_platform_interface 6.0.3 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 3.6.0 [firebase_core_platform_interface flutter flutter_web_plugins meta web]
- flutter_web_plugins 0.0.0 [flutter]
- leak_tracker 11.0.2 [clock collection meta path vm_service]
- leak_tracker_flutter_testing 3.0.10 [flutter leak_tracker leak_tracker_testing matcher meta]
- leak_tracker_testing 3.0.2 [leak_tracker matcher meta]
- lints 6.1.0
- matcher 0.12.19 [async meta stack_trace term_glyph test_api]
- material_color_utilities 0.13.0 [collection]
- meta 1.17.0
- path 1.9.1
- plugin_platform_interface 2.1.8 [meta]
- sky_engine 0.0.0
- source_span 1.10.2 [collection path term_glyph]
- stack_trace 1.12.1 [path]
- stream_channel 2.1.4 [async]
- string_scanner 1.4.1 [source_span]
- term_glyph 1.2.2
- test_api 0.7.10 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph]
- vector_math 2.2.0
- vm_service 15.1.0
- web 1.1.1

Additional context and comments

Current workaround: Change the break condition to if (querySnapshot.size <= 1).

Metadata

Metadata

Assignees

Labels

blocked: customer-responseWaiting for customer response, e.g. more information was requested.platform: webIssues / PRs which are specifically for web.plugin: databasetype: bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions