Skip to content

fix(firestore): dedupe listenForChanges subscriptions to prevent crash#2257

Open
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-remediation-5d4b
Open

fix(firestore): dedupe listenForChanges subscriptions to prevent crash#2257
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-remediation-5d4b

Conversation

@cursor
Copy link
Copy Markdown

@cursor cursor Bot commented Jun 4, 2026

Bug and impact

Trigger: A screen calls the same Firestore API with listenForChanges: true more than once (e.g. on tab switches, navigation callbacks, or screen refreshes). Each call adds another snapshot listener without cancelling the previous one.

Impact: After ~8–15 Firestore updates, callbacks multiply exponentially, the app slows dramatically, and can crash. Navigating away can also crash with Bad state: Cannot add new events after calling close when a snapshot arrives after the page event bus is destroyed but before the screen cancels API providers.

Fixes #2253.

Root cause

  • FirestoreAPIProvider.subscribeToApi() appended every subscription to a List<StreamSubscription> with no deduplication by API name (unlike SSEAPIProvider, which replaces existing subscriptions).
  • Page dispose closes the scope EventBus before Screen.dispose() cancels Firestore listeners, so late snapshot callbacks attempted to dispatch binding updates on a closed bus.

Fix

  • Track Firestore listeners in a Map<String, StreamSubscription> keyed by apiName and cancel/replace any existing subscription before subscribing (mirrors SSE provider behavior).
  • Skip snapshot delivery after the provider is disposed.
  • Ignore binding dispatches when the page event bus is already closed.

Validation

  • Added modules/ensemble/test/firestore_listen_dedup_test.dart covering subscription replacement and closed event-bus behavior.
  • Run from modules/ensemble: flutter test test/firestore_listen_dedup_test.dart

Duplicate check

Open in Web View Automation 

…sed event bus

Repeated invokeAPI calls with listenForChanges: true accumulated Firestore
snapshot listeners because subscribeToApi always appended to a list. Replace
the prior subscription for the same apiName (matching SSE provider behavior)
and skip callbacks after provider dispose.

Also ignore binding dispatches once the page event bus is closed, which avoids
crashes when a snapshot arrives after Page dispose but before Screen cancels
API providers.

Co-authored-by: Sharjeel Yunus <sharjeelyunus@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Firestore listenForChanges creates duplicate listeners causing app crash

1 participant