Baseflow / flutter_cached_network_image

Download, cache and show images in a flutter app
https://baseflow.com
2.44k stars 656 forks source link

errorWidget: Not trapping HTTPException when scrolling in AnimatedList #536

Closed GrahamDi closed 3 years ago

GrahamDi commented 3 years ago

πŸ› Bug Report

Issue: https://github.com/Baseflow/flutter_cached_network_image/issues/273 also refers but has been closed, yet the issue described is still present. I am experiencing exactly the same problems as described in this comment and the possible solutions suggested would seem to be realistic: https://github.com/Baseflow/flutter_cached_network_image/issues/273#issuecomment-565089938

I am using FirebaseAnimatedList in a chat app to display / add-to chat messages. These messages are a mix of text and images. I use CachedNetworkImage to handle the latter and it works very well, except when there are images in error AND I scroll quickly.

In my case the errors are HttpException: Invalid statusCode: 403 - permission denied - as I am trying to handle images on Cloud Storage that may not have a valid access token.

If I allow each image in error to show its error widget (in my case, a Text widget saying no image available) before scrolling it off the screen then all is well in the universe. If I quickly scroll the several images in error either up or down, thereby not giving CachedNetworkImage the chance to fully display the error widget then the app crashes (not just a console log in debug) and my Catcher implementation reports it but only from main.dart, not anywhere that I can usefully see a specific error in the code. The scrolling does not need to be very quick.

FYI, FirebaseAnimatedList is just an implementation of Dart's AnimatedList widget that builds based on a stream from a FB RTDB query. I would anticipate that this issue would also be the case even if I used a ListViewBuilder.

Expected behavior

I would expect the errorWidget: to fully trap the 403 (or what ever other error code) even if it has not completed displaying the error widget. However, it appears that it fails to do this or even propagates the error if it is still building the error widget. In either case I am unable to trap the error myself to handle the situation gracefully and stop the app crashing.

Reproduction steps

This is my code that uses CachedNetworkImage and is called from within my FirebaseAnimatedList.

CachedNetworkImage _showMessageImage() {
    return CachedNetworkImage(
      imageUrl: _messageImageUrl,
      fit: BoxFit.cover,
      width: 250.0,
      placeholder: (context, url) => Center(
        child: AdaptiveProgressIndicator(),
      ),
      errorWidget: (context, url, error) {
        var _errorText = "${S.of(context).imageUnavailable}\n";
        if (error.statusCode == 403) {
          // Code to handle 403 error corrections on the database. 
          // Not implemented when experiencing this issue.
        }
        return Center(
          child: Text(
            _errorText,
            style: TextStyle(
                color: Colors.redAccent[700], fontWeight: FontWeight.bold),
          ),
        );
      },
    );
  }

Configuration

CachedNetworkImage: 2.5.0

flutter doctor -v [√] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.21292.1000], locale en-ZA) β€’ Flutter version 1.22.5 at C:\flutter β€’ Framework revision 7891006299 (5 weeks ago), 2020-12-10 11:54:40 -0800 β€’ Engine revision ae90085a84 β€’ Dart version 2.10.4

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3) β€’ Android SDK at D:\Android β€’ Platform android-30, build-tools 30.0.3 β€’ ANDROID_HOME = D:\Android β€’ ANDROID_SDK_ROOT = D:\Android β€’ Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java β€’ Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) β€’ All Android licenses accepted.

[!] Android Studio (version 4.1.0) β€’ Android Studio at C:\Program Files\Android\Android Studio X Flutter plugin not installed; this adds Flutter specific functionality. X Dart plugin not installed; this adds Dart specific functionality. β€’ Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] VS Code (version 1.52.1) β€’ VS Code at C:\Users\dicki\AppData\Local\Programs\Microsoft VS Code β€’ Flutter extension version 3.18.1

[√] Connected device (1 available) β€’ AOSP on IA Emulator (mobile) β€’ emulator-5554 β€’ android-x86 β€’ Android 9 (API 28) (emulator)

! Doctor found issues in 1 category.

Platform:

Problem occurs on emulator and device.

renefloor commented 3 years ago

Can you give me a small reproducable example of a crashing app?

I would understand if the 403 exception is reported in the console or even any error reporting, but I've never seen an app crash.

The problem is that the widget only attaches an errorListener while it is visible (otherwise the widget might not even exist or showing a different image). The ImageStreamCompleter checks if there is anybody listener, otherwise prints the error in the logs. You can see the relevant code here: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/painting/image_stream.dart#L680

If you really have a crashing app that's indeed something we need to look into really quick, if you're just seeing it in the logs there is not much we can do about it other than convincing the Flutter team to change that part of the code.

GrahamDi commented 3 years ago

Thanks for the rapid response.

I will see what I can do regarding an example but given I am reading from a database it will not be very representative of the real world situation.

Regarding app crashes, I guess it depends on how you define a crash. This is what I see if I scroll slowly:

Screenshot_1610708658

and what I see if I scroll quickly (there is an error image under that dialogue, the dialogue comes from Catcher):

Screenshot_1610708846

Here is what I see in the debug console, whether or not the error dialogue has shown:

I/flutter (19520): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308 with error:
I/flutter (19520): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308
I/flutter (19520): [2021-01-15 13:12:45.193560 | Catcher | INFO] Setup localization lazily!
I/flutter (19520): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb with error:
I/flutter (19520): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb
GrahamDi commented 3 years ago

Ok, please see below an example app I have put together. It tries to access the same images (with invalid tokens) that my app does. I am also using ListView.builder rather than FirebaseAnimatedList.

I am unable to reproduce the 'crash' that I experience with my app using Catcher and don't really want to build that in unless I have to. What you will see though is when scrolling slowly, the output to the debug console is various repetitions of as follows in blue text in the VSCode console):

I/flutter ( 8812): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663795024.jpg?alt=media&token=bbd2d370-50bc-4192-8c75-e680cd9813af with error:
I/flutter ( 8812): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663795024.jpg?alt=media&token=bbd2d370-50bc-4192-8c75-e680cd9813af
I/flutter ( 8812): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12 with error:
I/flutter ( 8812): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12
I/flutter ( 8812): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5 with error:
I/flutter ( 8812): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5
I/flutter ( 8812): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308 with error:
I/flutter ( 8812): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308
I/flutter ( 8812): CacheManager: Failed to download file from https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb with error:
I/flutter ( 8812): HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb

However, if you scroll quickly you will see the above interspersed with the following messages (in white and red text):


════════ Exception caught by image resource service ════════════════════════════
HttpException: Invalid statusCode: 403, uri = https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663795024.jpg?alt=media&token=bbd2d370-50bc-4192-8c75-e680cd9813af
════════════════════════════════════════════════════════════════════════════════

These appear to be what causes 'crashes' (Catcher trapping) within my app. So I guess the question is, how to persuade my app's error trapping mechanism (Catcher) to ignore those exceptions?

My Code

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext ctxt) {
    return MaterialApp(
      home: ListDisplay(),
    );
  }
}

class ListDisplay extends StatelessWidget {
  static const List<String> urlList = [
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609664181749.jpg?alt=media&token=a0e135e8-6d11-4230-86c8-c9438995b6ce",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609664181749.jpg?alt=media&token=a0e135e8-6d11-4230-86c8-c9438995b6ce",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663795024.jpg?alt=media&token=bbd2d370-50bc-4192-8c75-e680cd9813af",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663795024.jpg?alt=media&token=bbd2d370-50bc-4192-8c75-e680cd9813af",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663773838.jpg?alt=media&token=248fb9ee-f086-497a-8810-e0ab64da201b",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663773838.jpg?alt=media&token=248fb9ee-f086-497a-8810-e0ab64da201b",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663721711.jpg?alt=media&token=dcefb3e8-b1ac-46db-88bf-f69a0307601a",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663721711.jpg?alt=media&token=dcefb3e8-b1ac-46db-88bf-f69a0307601a",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1605783375227.jpg?alt=media&token=8541ed67-8fd0-4435-83ac-549b6d1a89f6",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1605783375227.jpg?alt=media&token=8541ed67-8fd0-4435-83ac-549b6d1a89f6",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663721711.jpg?alt=media&token=dcefb3e8-b1ac-46db-88bf-f69a0307601a",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663721711.jpg?alt=media&token=dcefb3e8-b1ac-46db-88bf-f69a0307601a",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663691655.jpg?alt=media&token=b31dfea7-ffbe-489f-b7f4-fef87ea30de5",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609664181749.jpg?alt=media&token=a0e135e8-6d11-4230-86c8-c9438995b6ce",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609664181749.jpg?alt=media&token=a0e135e8-6d11-4230-86c8-c9438995b6ce",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666314264.jpg?alt=media&token=aed2cbd5-5214-49a9-a0b5-0a74cdae5adb",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609666163265.jpg?alt=media&token=8b498edd-09e2-4b7f-82bf-edad56a59308",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12",
    "https://firebasestorage.googleapis.com/v0/b/sailor-boy-dev.appspot.com/o/messageImages%2FvLOxXCzVVAOPeqO3WKgJbwycp6K2wMCN8h3pjIRIQwpe2Y1OSG5NYpS2%2Fimg_1609663901300.jpg?alt=media&token=bd1cf474-bf1a-4ee5-ba77-e1be0cfa6d12",
  ];

  @override
  Widget build(BuildContext ctxt) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Cached Network Image Error"),
      ),
      body: ListView.builder(
          itemCount: urlList.length,
          itemBuilder: (BuildContext ctxt, int index) {
            return Container(
              height: 100,
              width: 200,
              margin: const EdgeInsets.only(top: 5.0),
              padding: EdgeInsets.all(4.0),
              child: _showMessageImage(urlList[index]),
              // child: Text(litems[index]),
            );
          }),
    );
  }

  CachedNetworkImage _showMessageImage(String imageUrl) {
    return CachedNetworkImage(
      imageUrl: imageUrl,
      fit: BoxFit.cover,
      width: 250.0,
      placeholder: (context, url) => Center(
        child: CircularProgressIndicator(),
      ),
      errorWidget: (context, url, error) {
        // error is a HttpExceptionWithStatus object and
        // has properties:
        // message β†’ String; runtimeType β†’ Type;
        // statusCode β†’ int; uri β†’ Uri
        var _errorText = "Image unavailable\n";
        if (error.statusCode == 403) {}
        return Center(
          child: Text(
            _errorText,
            style: TextStyle(
                color: Colors.redAccent[700], fontWeight: FontWeight.bold),
          ),
        );
      },
    );
  }
}
renefloor commented 3 years ago

Ah, so it is not crashing, but Catcher catches it.

I've never used Catcher, so I'm not 100% sure how it works, but having a quick look at it I might have found a problem with catcher.

As you can see here: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/painting/image_stream.dart#L665 an error can be reported as 'silent'. Image loading errors are reported as silent.

Having a quick look at catcher I don't see them reading the 'silent' parameter from the ErrorDetails it receives here: https://github.com/jhomlala/catcher/blob/master/lib/core/catcher.dart#L385

GrahamDi commented 3 years ago

That makes a lot of sense, Rene. Thanks.

Having said above that I didn't want to, I was thinking of adding Catcher to my code example to see what happens. Think I will do that now and raise the issue with Jakub who is usually pretty responsive. Guess you can close this from your side.

Thanks again.

GrahamDi commented 3 years ago

Thanks for your insight into this issue, Rene. As you see, I raised it with Jakub (of Catcher) and he has incorporated silent message handling as an option in the package config. It is all working well now.

b-cancel commented 3 years ago

Hey @renefloor ! First of all thanks to you and your team for such a fantastic plugin!

but I was thinking... if this issue is so prevalent that the team has had to add a "notice" on the plugin page and since y'all also manage the plugin that is throwing the "error" that isn't wrapped in a try catch

Why not just wrap

throw HttpExceptionWithStatus(
        response.statusCode,
        'Invalid statusCode: ${response.statusCode}',
        uri: Uri.parse(cacheObject.url),
);

within the "web_helper.dart" file in the "flutter_cache_manager" plugin with a try catch?

That would eliminate the need for you too clarify, constantly be bothered by notifications here, and as a bonus, we could develop without worrying about something that isn't actually breaking anything without having to turn off tools that we use every day

renefloor commented 3 years ago

Because then you can't show an error widget. Flutter's image streams depend on catching errors and sending that to the listeners: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/painting/image_stream.dart#L844

juanlabrador commented 2 years ago

This link is an example with 403 status error

http://s3.amazonaws.com/enbola-prod/product/images/628d86ed8bf6fe3c3af8817f/original.628d86ed8bf6fe3c3af8817f.jpg?1653442285

maybe help

pkcell commented 2 years ago

Hey @renefloor, thanks for providing detailed feedback regarding the issue. I've been using this package for a while and despite this isolated scenario, it's excellent!

As everyone on this thread, I've been experiencing this issue, and mostly in production apps receiving bad reviews due to declined performance and increased battery usage. What happens is, the CDN would return a placeholder image along with a 404 response status code. The package (or the underlying dependency) will eventually crash the app due to a continues loop or queue of some sort. This caused serious performance and user experience issues.

My idea for bypassing the 404 or any other unsuccessful status code during the download cycle, came down to performing a HEAD call first, and provide a valid placeholder image url (Default inside the package could be useful). This in combination with the placeholder widget property made it possible to still utilise the package.

The workaround was to go and strip out the package contents of cached_network_image (and all the dependencies). Change the _updateFile method inside flutter_cache_manager/lib/src/web/web_helper.dart to first perform a HEAD HTTP request and interpret the status code before attempting to download the file.

Although this might not be the perfect solution, it's working quite well.

MrRobotElite627 commented 9 months ago

TΓ­tulo del problema (Issue):

Error al usar CachedNetworkImage en el paquete Flutter Cache Manager

DescripciΓ³n del problema:

Al intentar utilizar CachedNetworkImage en mi aplicaciΓ³n Flutter, estoy experimentando un error relacionado con HttpExceptionWithStatus en el archivo web_helper.dart del paquete flutter_cache_manager. Esto estΓ‘ ocurriendo cuando intento mostrar una imagen desde una URL remota utilizando CachedNetworkImage con un placeholder y un errorWidget personalizados.

Pasos para reproducir el problema:

  1. Incluir el paquete flutter_cache_manager y cached_network_image en un proyecto Flutter.
  2. Utilizar el siguiente cΓ³digo para mostrar una imagen desde una URL remota:

CachedNetworkImage( imageUrl: "http://via.placeholder.com/350x150", placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ),

Este es el Error que muestra por consola

  `./../../AppData/Local/Pub/Cache/hosted/pub.dev/flutter_cache_manager-3.3.1/lib/src/web/web_helper.dart:123:7:` Error:  

/iconthrow'isn't a type. iconthrow HttpExceptionWithStatus( ^^^^^^^^^ ../../../AppData/Local/Pub/Cache/hosted/pub.dev/flutter_cache_manager-3.3.1/lib/src/web/web_helper.dart:123:17: Error: Expected ';' after this. iconthrow HttpExceptionWithStatus( ^^^^^^^^^^^^^^^^^^^^^^^ ../../../AppData/Local/Pub/Cache/hosted/pub.dev/flutter_cache_manager-3.3.1/lib/src/web/web_helper.dart:123:40: Error: The 'records' language feature is disabled for this library. Try removing the package language version or setting the language version to 3.0 or higher. iconthrow HttpExceptionWithStatus( ^

InformaciΓ³n adicional:

VersiΓ³n de Flutter: 3.16.9
VersiΓ³n de cached_network_image: 3.3.1