flutterriverpodappwrite

Bad State: No Element - Using Appwrite and Riverpod in Flutter


I'm actually having issues while working with Appwrite and Riverpod, Whenever I try to get the comments from the appwrite server, I get bad state: no element error.

This Error mostly appears when I click to get the comment on a post, and sometimes after clicking on the hot-reload the error will stop and again it will appear.

I don't know what I'm actually doing wrong

Below is my screenshot and code

ref.watch(getRepliesToPostProvider(widget.postModel!)).when(
                  data: (post) {
                    return ref.watch(getLatestPostProvider).when(
                        data: (data) {
                          if (data.events.contains(
                            'databases.*.collections.${Common.postCollection}.documents.*.create',
                          )) {
                            post.insert(0, PostModel.fromMap(data.payload));
                          } else if (data.events.contains(
                            'databases.*.collections.${Common.postCollection}.documents.*.update',
                          )) {
                            final startingIndex =
                                data.events[0].lastIndexOf('documents.');
                            final endIndex =
                                data.events[0].lastIndexOf('.update');

                            var postId = data.events[0]
                                .substring(startingIndex + 10, endIndex);

                            var newPost = post
                                .where((element) => element.id == postId)
                                .first;

                            final postIndex = post.indexOf(newPost);
                            post.removeWhere((element) => element.id == postId);

                            newPost = PostModel.fromMap(data.payload);
                            post.insert(postIndex, newPost);
                          }

                          return Expanded(
                            child: ListView.builder(
                              padding: const EdgeInsets.all(0),
                              shrinkWrap: true,
                              scrollDirection: Axis.vertical,
                              physics: const ClampingScrollPhysics(),
                              itemCount: post.length,
                              itemBuilder: (BuildContext context, int index) {
                                var disPost = post[index];

                                final latestPost =
                                    PostModel.fromMap(data.payload);
                                bool isPostAlreadyPresent = false;
                                for (final postLoop in post) {
                                  if (postLoop.id == latestPost.id) {
                                    isPostAlreadyPresent = true;
                                    break;
                                  }
                                }

                                return ref
                                    .watch(userDetailsProvider(
                                        widget.postModel!.uid))
                                    .when(
                                        data: (user) {
                                          return Padding(
                                            padding: const EdgeInsets.only(
                                              left: 8.0,
                                              top: 2,
                                              right: 8,
                                              bottom: 2,
                                            ),
                                            child: Row(
                                              children: [
                                                CircularProfileAvatar(
                                                  user.profile,
                                                  radius: 20,
                                                  backgroundColor:
                                                      Colors.transparent,
                                                  borderWidth: 2,
                                                  initialsText: Text(
                                                    "AD",
                                                    style: TextStyle(
                                                        color: colorWhite),
                                                  ),
                                                  borderColor: colorWhite,
                                                  elevation: 5.0,
                                                  foregroundColor: Colors.brown
                                                      .withOpacity(0.5),
                                                  cacheImage: true,
                                                  imageFit: BoxFit.cover,
                                                  onTap: () {
                                                    print('adil');
                                                  },
                                                  showInitialTextAbovePicture:
                                                      false,
                                                ),
                                                const SizedBox(
                                                  width: 15,
                                                ),
                                                Expanded(
                                                  child: Text(disPost.text),
                                                ),
                                              ],
                                            ),
                                          );
                                        },
                                        error: (error, stk) => Container(),
                                        loading: () => Container());
                              },
                            ),
                          );
                        },
                        error: (error, stk) => ErrorText(
                              error: error.toString(),
                            ),
                        loading: () {
                          return Expanded(
                            child: ListView.builder(
                                padding: const EdgeInsets.all(0),
                                shrinkWrap: true,
                                scrollDirection: Axis.vertical,
                                physics: const ClampingScrollPhysics(),
                                itemCount: post.length,
                                itemBuilder: (BuildContext context, int index) {
                                  var disPost = post[index];

                                  return ref
                                      .watch(userDetailsProvider(
                                          widget.postModel!.uid))
                                      .when(
                                          data: (user) {
                                            return Padding(
                                              padding: const EdgeInsets.only(
                                                left: 8.0,
                                                top: 2,
                                                right: 8,
                                                bottom: 2,
                                              ),
                                              child: Row(
                                                children: [
                                                  CircularProfileAvatar(
                                                    user.profile,
                                                    radius: 20,
                                                    backgroundColor:
                                                        Colors.transparent,
                                                    borderWidth: 2,
                                                    initialsText: Text(
                                                      "AD",
                                                      style: TextStyle(
                                                          color: colorWhite),
                                                    ),
                                                    borderColor: colorWhite,
                                                    elevation: 5.0,
                                                    foregroundColor: Colors
                                                        .brown
                                                        .withOpacity(0.5),
                                                    cacheImage: true,
                                                    imageFit: BoxFit.cover,
                                                    onTap: () {
                                                      print('adil');
                                                    },
                                                    showInitialTextAbovePicture:
                                                        false,
                                                  ),
                                                  const SizedBox(
                                                    width: 15,
                                                  ),
                                                  Expanded(
                                                    child: Text(disPost.text),
                                                  ),
                                                ],
                                              ),
                                            );
                                          },
                                          error: (error, stk) => Container(),
                                          loading: () => Container());
                                }),
                          );
                        });
                  },
                  error: (error, stk) => ErrorText(
                    error: error.toString(),
                  ),
                  loading: () => const Loader(),
                ),

Screenshot

enter image description here enter image description here enter image description here


Solution

  • You've highlighted the problem:

    var newPost = post
        .where((element) => element.id == postId)
        .first;
    

    This throws an error; as mentioned here, it happens because the where didn't find anything matching.

    You can reproduce this by running this:

      final l = [1,2,3];
      
      final e = l.where((e) => e == 0).first;
    

    This could be happening because some Riverpod providers may not have finished fetching the data. It's important to be defensive and always handle the cases where something is missing.