32

I am new to flutter and i am building a social media App through tutorial which i am now customizing. Now I tried to add more input fields to a users profile page then i started getting the error below. When i could login my timeline page turned red with warning Bad state: field does not exist within the DocumentSnapshotPlatform

I ran Flutter clean and now my user cannot log into the app

I am getting this error:

E/flutter ( 3971): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform
E/flutter ( 3971): #0      DocumentSnapshotPlatform.get._findKeyValueInMap
package:cloud_firestore_platform_interface/…/platform_interface/platform_interface_document_snapshot.dart:82
E/flutter ( 3971): #1      DocumentSnapshotPlatform.get._findComponent
package:cloud_firestore_platform_interface/…/platform_interface/platform_interface_document_snapshot.dart:98
E/flutter ( 3971): #2      DocumentSnapshotPlatform.get
package:cloud_firestore_platform_interface/…/platform_interface/platform_interface_document_snapshot.dart:113
E/flutter ( 3971): #3      DocumentSnapshot.get
package:cloud_firestore/src/document_snapshot.dart:49
E/flutter ( 3971): #4      DocumentSnapshot.[]
package:cloud_firestore/src/document_snapshot.dart:56
E/flutter ( 3971): #5      new User.fromDocument
package:findemed/models/user.dart:46
E/flutter ( 3971): #6      _HomeState.createUserInFirestore
package:findemed/pages/home.dart:152
E/flutter ( 3971): <asynchronous suspension>
E/flutter ( 3971): #7      _HomeState.handleSignIn
package:findemed/pages/home.dart:60
E/flutter ( 3971): #8      _HomeState.initState.<anonymous closure>
package:findemed/pages/home.dart:46
E/flutter ( 3971): #9      _rootRunUnary (dart:async/zone.dart:1198:47)

The initial was pointing to this dart section of my home file

buildUsersToFollow() {
  return StreamBuilder(
    stream: usersRef.orderBy('timestamp', descending: true)
    .limit(0)
    .snapshots(),
    builder: (context, snapshot) {
      if (!snapshot.hasData) {
        return circularProgress(context);
      }
      List<UserResult> userResults = [];
      snapshot.data.docs.forEach((doc) {
        User user = User.fromDocument(doc);
        final bool isAuthUser = currentUser.id == user.id;
        final bool isFollowingUser = followingList.contains(user.id);
        // remove auth user from recommended list
        if (isAuthUser) {
          return;
        } else if (isFollowingUser) {
          return;
        } else {
          UserResult userResult = UserResult(user);
          userResults.add(userResult);
        }
        });


Now its pointing to this snippet:

factory User.fromDocument(DocumentSnapshot doc) {
    return User(
      id: doc['id'],
      email: doc['email'],
      username: doc['username'],
      photoUrl: doc['photoUrl'],
      displayName: doc['displayName'],
      bio: doc['bio'],      
      fullNames: doc['fullNames'],
      practice: doc['practice'],
      speciality: doc['speciality'],
      phone: doc['phone'],
      mobile: doc['mobile'],
      emergency: doc['emergency'],
      address: doc['address'],
      city: doc['city'],
      location: doc['location'],
    );
  }

and this is the other bit of code pointed out in the stack

currentUser = User.fromDocument(doc);
    print(currentUser);
    print(currentUser.username);
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Ace
  • 390
  • 1
  • 4
  • 11
  • 1
    Please edit the question to 1) indicate which line of code this error refers to, and 2) state clearly what you expect this code to do instead (especially given that you requested a limit of 0 documents). – Doug Stevenson Nov 22 '20 at 01:36

28 Answers28

58

For the latest version of cloud_firestore (2.4.0 or above) finally i found the solution:

And the older version of cloud_firestore it is solved by simply adding ?? at the end to avoid a null value:

factory User.fromDocument(DocumentSnapshot doc) {
   return User(
      id: doc.data()['id'] ?? '',
   );
}

but in the new version that not possible because return Bad state

factory User.fromDocument(DocumentSnapshot doc) {
   return User(
       id: doc.get('id')
   );
}

And it is solved by simply checking that the doc contains the key:

factory User.fromDocument(DocumentSnapshot doc) {
   return User(
      id: doc.data().toString().contains('id') ? doc.get('id') : '', //String
      amount: doc.data().toString().contains('amount') ? doc.get('amount') : 0,//Number
      enable: doc.data().toString().contains('enable') ? doc.get('enable') : false,//Boolean
      tags: doc.data().toString().contains('tags') ? doc.get('tags').entries.map((e) => TagModel(name: e.key, value: e.value)).toList() : [],//List<dynamic>
   );
}

Hope this helps, regards! :)

silexcorp
  • 1,151
  • 1
  • 12
  • 13
24

Change your factory to this:

factory User.fromDocument(DocumentSnapshot doc) {
  return User(
    id: doc.data()['id'],
    email: doc.data()['email'],
    username: doc.data()['username'],
    photoUrl: doc.data()['photoUrl'],
    displayName: doc.data()['displayName'],
    bio: doc.data()['bio'],      
    fullNames: doc.data()['fullNames'],
    practice: doc.data()['practice'],
    speciality: doc.data()['speciality'],
    phone: doc.data()['phone'],
    mobile: doc.data()['mobile'],
    emergency: doc.data()['emergency'],
    address: doc.data()['address'],
    city: doc.data()['city'],
    location: doc.data()['location'],
  );
}
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Rishi Malgwa
  • 339
  • 1
  • 11
  • 1
    Changing to `doc.data()` fixes one problem then i had to address the `.limit(0)` by making it a positive int and it runs – Ace Nov 23 '20 at 08:14
  • 9
    i tried this, but it gives The operator '[]' isn't defined for the type 'Object'. – s3v3ns Aug 11 '21 at 16:29
  • 1
    @s3v3ns You can use this workaround for that error. `(e.data() as dynamic)['field']`. Ugly but it works. Or create a dynamic alias `final _snapshot = snapshot as dynamic;`. Maybe there's a better way, I'm still learning. – Adrian Moisa Sep 19 '21 at 07:34
  • Thanks Adrian, very useful workaround. Is there an explanation why casting to a dynamic works? I was using `context.watch().data()` when I got the error that @s3v3ns mentioned. – Petar Bivolarski Dec 12 '21 at 20:17
18

I had the same problem and I solved it by asking if the parameter exists.

This was my previous code:

if(widget.document['imageUrl'] == null)//here was my error, I was calling a field that did not exist in the document
  Container(
    child:Icon(
      Icons.image,
      size: 20.0,
      color: Colors.grey,
    ),
  ),

This is how it works for me:

if(widget.document.data().containsKey('imageUrl'))
  Container(
    child:Icon(
      Icons.image,
      size: 20.0,
      color: Colors.grey,
    ),
  ),
Cosmin Staicu
  • 1,809
  • 2
  • 20
  • 27
7

This issue can also happen by passing wrong attribute name that does not exist in the document , while displaying document data in a builder method. This solved the issue for me.

Haseeb Sajjad
  • 224
  • 4
  • 7
3

Simple solution would be using data() from the DocumentSnapshot and cast it as Map<String,dynamic>, and finally you can check if key exists on Map or not as shown in given code snippets.

fireStore.collection('transactions').get().then((QuerySnapshot querySnapshot) {
  List<TransactionModel> transactions = [];
  querySnapshot.docs.forEach((DocumentSnapshot doc) {
    transactions.add(TransactionModel.fromJson(doc.data() as Map<String,dynamic>));
  });
  onResponse(FireStoreApiResponse.withSuccess(transactions));
}).catchError((onError) {
  onResponse(FireStoreApiResponse.withError(onError));
});

In TransactionModel class

TransactionModel.fromJson(Map<String, dynamic> json) {
date = json['date'];
memberId = json['member_id'];
if (json.containsKey("member_contact")) memberContact = json['member_contact'];
if (json.containsKey("member_name")) memberName = json['member_name'];
packageId = json['package_id'];
grossAmount = json['gross_amount'];
discount = json['discount'];
netAmount = json['net_amount']; }
Anil Bhomi
  • 691
  • 7
  • 12
3

Error (Bad State : Field Does not exists within the document) only Occurs when you Type Case Sensitive Field name in your Flutter Code or field name which does exists in yours firestore collections fields.

Remember field Names are Case Sensitive so you have to use same field as mentioned in your firestore collection field

For Example:- Your Firebase Firestore Collection Field Contains 'Username' field and you have used 'username' in your Flutter code then this error occurs. So to fix this error use same field name as mentioned in Firestore

This is Cloud FireStore Collection Fields Contain "UserName", etc so you have to use Exactly same in your Flutter Code Check Cloud FireStore Collection Fields

due to case Sensitivity This is correct because collections field exist as ("UserName") in Firestore Collections and used ("UserName") in Flutter Code

Correct FieldName forFlutter Code due to case Sensitivity This is Wrong because collections field exist as ("UserName") in Firestore Collections and used ("username") in Flutter Code Wrong FieldName forFlutter Code

If you need more help just ping me... Happy Coding

3

Implement extension method for the DocumentSnapshot type.

In 2022 the simplest solution for me is to implement an extension method of the DocumentSnapshot type. This can be setup to overwrite the get method entirely (no example shown here), or implement custom methods for more strongly-typed data (example shown below).

The core functionality of the methods should follow the pattern noted in this answer. If you create this extension in a separate file and import it you'll also need to import the cloud_firestore dependency into that file in order to access the DocumentSnapshot type.

In this example the new methods become available directly on the snapshot.

extension CustomGetters on DocumentSnapshot {
  int getInt(key) {
    return this.data().toString().contains(key) ? this.get(key) : 0;
  }
  String getString(key) {
    return this.data().toString().contains(key) ? this.get(key) : '';
  }
}

To access, just call your custom methods rather than the usual get method:

/**...fetch the snap...then...**/
snap.getInt('id');
snap.getString('username');
Casey
  • 56
  • 1
  • 4
2

A better and simple way

factory User.fromDocument(DocumentSnapshot snap) {

   var doc = snap.data();
   id: doc['id'],
   email: doc['email'],
   ......
   ......
      
}
Shreyash Jain
  • 112
  • 1
  • 2
2

I has the same issue. Later found that it was due to a trailing space in the key name in Firestore.

2

This error occurs when any parameter key is missing or has a typo in it as compared to firebase declared fields.

For Example: inside the firebase document, we have a key/value username.

username: "Ali Murtaza"

Now if inside the model if we miss it or write it like this:

username: doc["usernameeeeee"] as String

then bad state: field does not exception will occur.

To handle this case, we have to check whether the document we are fetching contains the particular field or not? To check this:

username: doc.data()!.containsKey("username")
              ? doc["username"] as String
              : "Username Key Does Not Exist inside Firebase Document",
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ali Murtaza
  • 414
  • 4
  • 9
1

**

Be sure the name of the document on your builder is the same name on your firestore database document name.

**

kojo justine
  • 103
  • 1
  • 12
1

Make sure to convert the documentSnapshot.data() to a Map<String, dynamic> first. The thing is that when you are searching for the key-value if the key is not available then it throws an error of bad state. To handle this you can use optional types available with the null safety feature. A sample code is given below:

final _data = documentSnapshot.data() as Map<String, dynamic>;
final CourseModel _courseModel = CourseModel(
  name: _data['name'] ?? "",
  imageLink: _data['imageLink'] ?? "",
  details: _data['details'] ?? "",
  trending: _data['trending'] ?? false,
  id: _data['id'] ?? "",
  discount: _data['discount'] ?? 0,
); 

On top you can see that there is a ?? to handle if there is no value available for a key. For example if the discount is not available then by default it sets the value to 0.

Imran Sefat
  • 528
  • 4
  • 6
1

I encountered the same problem and I solve it using the extension:

// extension.dart
import 'package:cloud_firestore/cloud_firestore.dart';

extension DocumentSnapshotExtensions on DocumentSnapshot {
  Map<String, dynamic> get dataMap {
    return this.data() as Map<String, dynamic>? ?? {};
  }
}

and use .dataMap instead of .data()

// don't use these:
// final username = doc.data()['username'];
// final username = doc['username'];

// use this:
final username = doc.dataMap['username'];

and happy coding ;)

then for your case will look like this:

factory User.fromDocument(DocumentSnapshot doc) {
    final dataMap = doc.dataMap;
    return User(
      id: dataMap['id'],
      email: dataMap['email'],
      username: dataMap['username'],
      photoUrl: dataMap['photoUrl'],
      displayName: dataMap['displayName'],
      bio: dataMap['bio'],      
      fullNames: dataMap['fullNames'],
      practice: dataMap['practice'],
      speciality: dataMap['speciality'],
      phone: dataMap['phone'],
      mobile: dataMap['mobile'],
      emergency: dataMap['emergency'],
      address: dataMap['address'],
      city: dataMap['city'],
      location: dataMap['location'],
    );
  }
Ming Chu
  • 1,315
  • 15
  • 13
0

I think this is because of the .limit(0) clause.

Ivan
  • 129
  • 3
  • 6
0

this also happens when the document which you are calling is null.

Gaurav Raj
  • 91
  • 1
  • 3
0

I solved this error by changing my query to update the values in the database rather than set them because apparently one field was being deleted and hence could not retrieve its value. This can help people who face the same error and have the same set up as mine.

danmakzz
  • 3
  • 2
0

Instead of Using this:

factory User.fromDocument(DocumentSnapshot doc) {
    return User(
      id: doc['id'],
      email: doc['email'],
      username: doc['username'],
      photoUrl: doc['photoUrl'],
      displayName: doc['displayName'],
      bio: doc['bio'],      
      fullNames: doc['fullNames'],
      practice: doc['practice'],
      speciality: doc['speciality'],
      phone: doc['phone'],
      mobile: doc['mobile'],
      emergency: doc['emergency'],
      address: doc['address'],
      city: doc['city'],
      location: doc['location'],
    );
  }

I used ::

factory User.fromDocument(DocumentSnapshot doc) {
    return User(
      id: doc.get('id'),
      email: doc.get('email'),
      username: doc.get('username'),
      photoUrl: doc.get('photoUrl')
      displayName: doc.get('displayName'),
      bio: doc.get('bio'),      
      fullNames: doc.get('fullNames'),
      practice: doc.get('practice'),
      speciality: doc.get('speciality'),
      phone: doc.get('phone'),
      mobile: doc.get('mobile'),
      emergency: doc.get('emergency'),
      address: doc.get('address'),
      city: doc.get('city'),
      location: doc.get('location'),
    );
  }

It Solved the problem for me...

SAch
  • 69
  • 8
0

To check Firebase and Local value same key of all data ie, doc['id']

here 'id' is key check same as in your firestore.

id: doc['id'],
  email: doc['email'],
  username: doc['username'],
  photoUrl: doc['photoUrl'],
  displayName: doc['displayName'],
  bio: doc['bio'],      
  fullNames: doc['fullNames'],
  practice: doc['practice'],
  speciality: doc['speciality'],
  phone: doc['phone'],
  mobile: doc['mobile'],
  emergency: doc['emergency'],
  address: doc['address'],
  city: doc['city'],
  location: doc['location'],

check and rerun

0

Use this :

Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
data['SOMEKEY'].toString();
int.parse(data['SOMEKEY'].toString());
for boolean use if(data['SOMEKEY'] == true)
0

let say final Map<String, dynamic> doc so you can check for any field available in doc variable doc.keys.contains('anyField') it will true if field available otherwise false.

Mohsin AR
  • 2,998
  • 2
  • 24
  • 36
0

This error is because, The field you are calling from the document does not exists. Even a single field can cause this error.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Abin vs
  • 103
  • 5
0

Accepted answer did not work for me, the below code worked for me. If field is not available from Firebase, the code below will still work

    factory User.fromDocument(DocumentSnapshot doc) {

      Map<String, dynamic> json = doc.data() as Map<String, dynamic>;

      return User(
        id: json['id'],
        email: json['email'],
        username: json['username'],
        photoUrl: json['photoUrl'],
        displayName: json['displayName'],
        bio: json['bio'],      
        fullNames: json['fullNames'],
        practice: json['practice'],
        speciality: json['speciality'],
        phone: json['phone'],
        mobile: json['mobile'],
        emergency: json['emergency'],
        address: json['address'],
        city: json['city'],
        location: json['location'],
      );
    }
0

None of the solutions worked for me. I had a similar error, so what I did is I remade the field in firestore database by first printing each field separately, then identifying the error causing field, and simply deleting and adding that field again in firestore from Console. It worked for me.

Arsh Ansari
  • 11
  • 1
  • 3
0

with the new firebase libraries it is a little different but very similar, to solve it I did it in the following way

Future<List<ArticleModel>> readArticles() async {
    List<ArticleModel> listArticle = [];
    await articles.get().then((QuerySnapshot querySnapshot) {
      for (var doc in querySnapshot.docs) {
        try {
          Map _json = (doc.data() as Map);
          ArticleModel articleModel = ArticleModel(
              title: _json['title'],
              description: _json['description'],
              imageURL: _json['imageURL'],
              groupTheme: _json['groupTheme'] ?? 'General', //this is the value that does not exist
              idArticulo: doc.id);
          listArticle.add(articleModel);
        } catch (e) {
          throw 'Error: $e';
        }
      }
    });

    return listArticle;
  }
0

make sure u are calling the right database name and for exmaple in firesotre the name of my data was image_url but i called it imageUrl after i called the correct name it works

0

In my case:

the name of the field in Firebase did not match the name of the field in Flutter. For example:

Firebase = 'image_url' -> Flutter 'image_URL' / error Firebase = 'image_url' -> Flutter 'image_url' / correct

0

The reason for this error is when you want to display that item on a screen which is not yet stored in firestore database for example you want to show the username of the user which is you think save in database when name not saved or you misspelled the key name of the username like below example Actually

"username": name;

you type

"usernam" 

cross check the key-value name or confirm whether this value is saved in the database or not.

I hope this will explanation help you

toyota Supra
  • 3,181
  • 4
  • 15
  • 19
-1

Unless you're careless, this error is not code related. There may be differences between the fields in the database and the data in its class.

Example: Class Student{String? name,String? department,String? school}

Database: 1-> name=xxx, no=xxx 2-> name=yyy, no=yyy ,school=yyy

All fields must match correctly.