Flutter Firestore not giving updated data when I add a field to a document from the console

Viewed 541

I'm facing an odd bug in Flutter Firestore 2.5.3 where if I add a new field (customer_type) to a document in the Firebase Console, the app fails to retrieve the newly added field and throws an exception:

CastError (type 'Null' is not a subtype of type 'String' in type cast)

But it isn't null. I added the new field with the value from the Firebase Console. It's there in the document. Turns out Firebase is getting the old document data without the newly added field.

I'm using a StreamProvider from Riverpod. Here's the code:

static Stream<Customer?> _watchCustomer(final ProviderRefBase ref) async* {
  final auth = await ref.watch(authProvider.last);
  if (auth == null) {
    yield null;
  } else {
    final customerRef = _db.collection('customers').toCustomerRef(auth.uid);
    await for (var customer in customerRef.snapshots().map((doc) => doc.data())) yield customer;
  }
}

What could be going wrong?

EDIT:

All the names, collection & field are correct and so is their type. If I re-install the app or fully clear app storage, the same exact code will work just fine. However, if I just clear the cache it doesn't work. It impedes my workflow when debugging and I'd like to know why it's happening. For additional reference, here is my "Customer" model:

Customer.fromMap(final String documentID, final Map<String, dynamic> map)
  : id = documentID,
    name = map['customer_name'] as String,
    mobile = map['customer_mobile'] as String,
    type = map['customer_type'] as String;

It's set to be non-nullable, because I'm establishing a strict schema. But that shouldn't be a concern, cause it isn't null in the database. I've added customer_type to all my documents in the collection. And none of them have the value set to null.

Which could only mean that the map that I get from Firestore, couldn't find the requisite key. Which means I'm still getting the old data (without the new field) from Firestore. What gives? It should give me the updated data when I clear the cache at least.

2 Answers

Because your code is working properly until you add the new field in Firestore console, it means that the problem is with your new field.

The problem is you either added a field in Firestore spelled differently (case sensitive or typo) from your model (class Customer) or the type is not appropriate (e.g. you try to read an int from a String, or you try to read an array from a map, etc.)

Let me know if this does not help?

What I know so far is that the stream returns an immediate local snapshot of the Document before fetching the updated version from the server. Which makes sense; except that if I clear the cache, then it should go to the server directly and not give me any error - which doesn't happen.

I think Firestore might be storing the local snapshot in more places than just the cache, but this is merely speculation on my end.

Currently, I've patched the issue by doing a simple null check in the constructor:

type = map['customer_type'] as String? ?? 'customer'

This fix is, however, inconclusive and I won't be marking this as the answer as I feel a proper explanation of what's happening is due.

Related