Skip to content

[flutter_svg] Failed pending cache loads escape as unhandled errors and prevent retries #196285

Open
flutter/packages
#13613

Description

@deandreamatias

Steps to reproduce

  1. In the flutter_svg package on main, add and run the test below.
  2. Complete the first load with an error.
  3. Observe the unhandled asynchronous error. Then request the same key again with a successful loader; the failed pending future is reused and the loader is not called.
  4. To see the user-facing impact, load an SVG with SvgPicture.network while the connection drops. The errorBuilder runs, but the escaped error reaches PlatformDispatcher.onError.

Expected results

The future returned by putIfAbsent completes with the original error so callers can handle it. No separate unhandled asynchronous error reaches the zone or PlatformDispatcher.onError. The failed pending entry is removed, allowing a later request for the same key to retry.

Actual results

The success-only pendingResult.then callback creates a derived future with no error handler. When loading fails, that derived future surfaces an unhandled asynchronous error. The failed future also remains in _pending, so subsequent requests for the same key replay the failure instead of retrying.

With SvgPicture.network, errorBuilder runs, but the widget does not expose the escaped future for the application to catch. This can reach PlatformDispatcher.onError and be recorded by Crashlytics as a fatal error.

Related: dnfield/flutter_svg#881
Related PR: dnfield/flutter_svg#1104

Code sample

Code sample
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter_svg/src/cache.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('Failed load is evicted from pending and retried', () async {
    final cache = Cache();
    final error = StateError('boom');
    final completer = Completer<ByteData>();
    final Future<ByteData> future = cache.putIfAbsent(
      'key',
      () => completer.future,
    );

    completer.completeError(error);
    await expectLater(future, throwsA(same(error)));
    await null;

    var calls = 0;
    await cache.putIfAbsent('key', () async {
      calls++;
      return ByteData(1);
    });
    expect(calls, 1);
  });
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
Reproduced on main: running the test above fails with an unhandled Bad state: boom error.
With the fix, flutter test test/cache_test.dart passes (5 tests).

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.47.9, on Ubuntu 24.04.5 LTS 6.8.0-1064-azure,
    locale C.UTF-8) [39ms]
    • Flutter version 3.47.9 on channel stable at /home/codespace/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision c197ca5199 (12 days ago), 2026-10-29 10:10:20 -0400
    • Engine revision 89c39edfdf
    • Dart version 3.13.7
    • DevTools version 2.60.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop,
      enable-windows-desktop, enable-android, enable-ios, cli-animations,
      enable-native-assets, enable-record-use, enable-swift-package-manager,
      omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration

[✗] Android toolchain - develop for Android devices [30ms]
    ✗ Unable to locate Android SDK.
      Install Android Studio from:
      https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK
      components.
      (or visit https://flutter.dev/to/linux-android-setup for detailed
      instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[✗] Chrome - develop for the web (Cannot find Chrome executable at
    google-chrome) [13ms]
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✗] Linux toolchain - develop for Linux desktop [186ms]
    • Ubuntu clang version 18.1.3 (1ubuntu1)
    • cmake version 3.28.3
    ✗ ninja is required for Linux development.
      It is likely available from your distribution (e.g.: apt install
      ninja-build), or can be downloaded from
      https://github.com/ninja-build/ninja/releases
    • pkg-config version 1.8.1
    ✗ GTK 3.0 development libraries are required for Linux development.
      They are likely available from your distribution (e.g.: apt install
      libgtk-3-dev)
    ! Unable to access driver information using 'eglinfo'.
      It is likely available from your distribution (e.g.: apt install
      mesa-utils)

[✓] Connected device (1 available) [46ms]
    • Linux (desktop) • linux • linux-x64 • Ubuntu 24.04.5 LTS 6.8.0-1064-azure

[✓] Network resources [289ms]

! Doctor found issues in 3 categories.

Activity

  1. added
    c: crashStack traces logged to the console
    packageflutter/packages repository. See also p: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    p: flutter_svgThe Flutter SVG drawing packages
    on Nov 10, 2026
  2. mbcorona commented on Nov 10, 2026

    @mbcorona
    Member

    Thanks for the report and the test @deandreamatias.

    Routing to the engine team to review the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: crashStack traces logged to the consolehas reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: flutter_svgThe Flutter SVG drawing packagespackageflutter/packages repository. See also p: labels.team-engineOwned by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions