Skip to content

Firestore: pending writes silently lost when issued around disableNetwork() / enableNetwork() #8440

Description

@eli1stark

[REQUIRED] Step 1: Describe your environment

  • Android Studio version: any (reproduced on emulator and physical device)
  • Firebase Component: Firestore
  • Component version: reproduced with firebase-bom:33.1.1 (firebase-firestore); originally observed June 2024, still relevant as of the FlutterFire triage in July 2026

[REQUIRED] Step 2: Describe the problem

Steps to reproduce:

When a write (e.g. update() with FieldValue.increment()) is issued while the network is being toggled via disableNetwork() / enableNetwork(), the write can be silently dropped — it never reaches the backend and no error is surfaced. Starting from a field value of 0, calling increment(-1) followed by increment(+1) across a network toggle can leave the server value at -1 (or lower after repeated runs) instead of 0.

This was originally reported against FlutterFire in firebase/flutterfire#12952 with a Flutter reproduction (roughly 40–50% hit rate per attempt, near-certain when repeated). A FlutterFire maintainer then reproduced it in a pure native Android project using this SDK directly, with no Flutter involved: TarekkMA/firebase-android-reproduction @ ff-issue/12952. On that basis the FlutterFire issue was closed as an upstream native SDK bug (comment) — FlutterFire only forwards increment/disableNetwork/enableNetwork to this SDK. I'm filing this issue here to continue the investigation, as no upstream issue existed yet.

Trigger sequence (from the original report, translated to the Android SDK):

FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference doc = db.collection("test").document("doc"); // field "v" starts at 0

Map<String, Object> minusOne = new HashMap<>();
minusOne.put("v", FieldValue.increment(-1));
Map<String, Object> plusOne = new HashMap<>();
plusOne.put("v", FieldValue.increment(1));

doc.update(minusOne);      // not awaited, as in real offline-capable apps
db.disableNetwork();
doc.update(plusOne);
db.enableNetwork();

Repeat the sequence a few times (a 2–3 second pause between runs is enough; firing many sequences concurrently makes it near-deterministic) and watch the document via a snapshot listener or the console.

The disableNetwork()/enableNetwork() calls are only a deterministic stand-in for an unstable real-world connection — the original report reproduced the same loss on a physical device with a genuinely flaky network, it is just far more cumbersome to trigger that way.

Expected result

Both queued writes are eventually delivered once the network is re-enabled — offline mutations are documented as queued and synced when connectivity returns. The field ends at 0 after every -1/+1 pair, every time.

Actual result

Intermittently (~40–50% of attempts in the Flutter harness, also confirmed in the native Android repro linked above) one of the writes is lost: the field ends at -1, and repeated runs drift further negative. The lost write's task never fails — there is no error signal that the mutation was dropped, so the client and server silently diverge.

Relevant Code:

Note: the same behavior was also reproduced on iOS through FlutterFire, so the defect is likely shared across the native SDKs' offline mutation queue logic rather than being Android-specific.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions