Skip to content

Failure of ImageProvider's error handling #44579

@slightfoot

Description

@slightfoot

@escamoteur and I have been working on an app and a bug in our revealed a whole set of issues within the framework for handling image errors. A bug in our app tried to load a Image file with zero-byte file size which causes the follow chain of events to occur.

Chain of events

  1. ImageProvider.resolve sets up a uncaught exception handler and calls obtainKey and load on FileImage to load the image codec. The way it handles errors here seems very complicated for what is actually required.
  2. FileImage.load is called and creates a MultiFrameImageStreamCompleter and returns it with the codec loading asynchronously.
  3. FileImage._loadAsync later returns a null when it detects the 0 length file.
  4. MultiFrameImageStreamCompleter constructor had setup an error handler for codec loading failures; however because null is reported as a successful response the value is passed to MultiFrameImageStreamCompleter._handleCodecReady which asserts that it can't be null. Because this function does not return a Future the assertion is passed down and caught by our uncaught exception handler rather than by the actual codec failure handler. Secondly this codec failure handler gobbles the error and does not pass it down to the ImageStream?
  5. The uncaught exception is passed over to be handled by ImageProvider.resolve.handleError which then further attempts to set the completer on the ImageStream to its own to error completer which further causes an assertion because a ImageStreams completer can only be set once, and it was previously successfully set by the synchronous load callback;

Thoughts

There are several failures in this chain.. all of which should never have occurred. I am happy to address these as bugs, but to be honest it seems as though a rethink of how ImageProvider errors are handled is probably in order.

It should also be possible to handle these errors gracefully and not silently from within the Image widget. I think we've needed a errorBuilder on it for a long time, and since we now have an error listener as part of ImageCompleter it should be accessible to the end developer.

Steps to Reproduce

Run the example code below in Debug mode of your IDE.

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart' as pp;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final tmp = await pp.getTemporaryDirectory();
  final blank = await File(p.join(tmp.path, 'test.jpg')).create(recursive: true);
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Example'),
        ),
        body: Center(
          child: Image.file(blank),
        ),
      ),
    ),
  );
}

Logs

[√] Flutter (Channel dev, v1.10.15, on Microsoft Windows [Version 10.0.17763.805], locale en-GB)
    • Flutter version 1.10.15 at C:\Android\flutter
    • Framework revision fbabb264e0 (10 days ago), 2019-11-02 01:36:07 +0300
    • Engine revision 8ea19b1c76
    • Dart version 2.6.0 (build 2.6.0-dev.8.2 bbe2ac28c9)

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at C:\Android\SDK
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • ANDROID_HOME = C:\Android\SDK
    • Java binary at: C:\Android\Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 3.5)
    • Android Studio at C:\Android\Studio
    • Flutter plugin version 39.0.3
    • Dart plugin version 191.8423
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[√] IntelliJ IDEA Ultimate Edition (version 2019.2)
    • IntelliJ at C:\Users\Simon\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\192.6817.14
    • Flutter plugin version 39.0.4
    • Dart plugin version 192.6527

[√] VS Code, 64-bit edition (version 1.27.2)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension version 2.18.0

[√] Connected device (3 available)
    • iPhone     • 192.168.188.108:5555 • android-x86    • Android 8.0.0 (API 26)
    • Chrome     • chrome               • web-javascript • Google Chrome 78.0.3904.87
    • Web Server • web-server           • web-javascript • Flutter Tools

• No issues found!

Metadata

Metadata

Assignees

Labels

a: error messageError messages from the Flutter frameworka: imagesLoading, displaying, rendering imagescustomer: wednesdayHump day Q&Aframeworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions