Home > Software design >  FirebaseException only thrown when GetOptions(source: Source.server)
FirebaseException only thrown when GetOptions(source: Source.server)

Time:09-22

When requesting Firestore data using my flutter app without network connection, I would expect a FirebaseException when the data is not cached already.

Example:

try {
  return await FirebaseFirestore.instance.collection("songs").get();
} on FirebaseException catch (e) {
  log(e.toString());
  return null;
}

But this never happens. get() returns a QuerySnapshot with an empty list of documents instead. Note: I just removed the cached data from the device, so there shouldn't exist any cached documents.

When explicitly requesting the data only from server, then the exception is thrown as expected:

try {
  return await FirebaseFirestore.instance.collection("songs")
      .get(GetOptions(source: Source.server);
} on FirebaseException catch (e) {
  log(e.toString());
  return null;
}

Is this expected behavior? My client shouldn't even know if this collection exists. How should the client distinguish between a failed network request and a successful request, but with an empty collection on the server?

CodePudding user response:

How should the client distinguish between...

I usually find it easier to solve this type of problem by changing that question to a "Why". So: why should the client distinguish between a failed network request and a successful request, but with an empty collection on the server?

Usually this is because you're looking to write/update a document, and there may be conflicting writes from different users. In such scenarios you should likely use a transaction, which then also solves the problem of getting a false non-existing document snapshot, as the transaction will auto-retry in cases when that happens.

CodePudding user response:

To distinguish a failed network request with no documents of the collection in cache from a successful network request with an empty collection on server, you can use the isFromCache property of the Snapshot which is returned by the get() method. Thanks to Frank van Puffelen!

The following workaround solves this problem for me:


final snapshot = return await FirebaseFirestore.instance
    .collection("songs").get();
if (snapshot.docs.isEmpty && snapshot.metadata.isFromCache) {
  return null;
} else {
  return snapshot;
}

...but not for 100%, which if fine for my app. I think this is just a limitation of caching. You never know if the data in cache is really up-to-date.

  • Related