Skip to content

[vector_graphics] A failed asynchronous load is reported as unhandled even when errorBuilder handles it #194705

Closed
flutter/packages
#13315

Description

@mtallenca

Steps to reproduce

  1. Show a VectorGraphic (or a flutter_svg SvgPicture) whose BytesLoader.loadBytes returns a future that completes with an error — for example an SvgPicture.asset on web whose asset fetch fails because the network dropped.
  2. Optionally give it an errorBuilder.

Expected results

The error is handled: _loadAssetBytes catches it and the widget shows errorBuilder (or nothing).

Actual results

The widget does catch it and shows errorBuilder, but the same error is also delivered to the zone as an unhandled error — PlatformDispatcher.onError / runZonedGuarded, so crash reporters record it as fatal.

The cause is in _VectorGraphicWidgetState._loadPicture (packages/vector_graphics/lib/src/vector_graphics.dart):

_pendingPictures[key] = result;
result.whenComplete(() {
  _pendingPictures.remove(key);
});
return result;

whenComplete returns a new future that completes with result's error, and nothing listens to it, so it is reported as unhandled even though result itself is awaited inside a try/catch.

The existing test VectorGraphicsWidget can handle errors from bytes loader doesn't catch this because its ThrowingBytesLoader.loadBytes throws synchronously, before whenComplete is reached. Making loadBytes async reproduces it: the test fails with the UnimplementedError reported by the test framework.

Code sample

class AsyncThrowingBytesLoader extends BytesLoader {
  const AsyncThrowingBytesLoader();

  @override
  Future<ByteData> loadBytes(BuildContext? context) async {
    throw UnimplementedError('Test exception');
  }
}

testWidgets('handles an asynchronous error from bytes loader', (WidgetTester tester) async {
  await tester.pumpWidget(
    VectorGraphic(
      loader: const AsyncThrowingBytesLoader(),
      width: 100,
      height: 100,
      errorBuilder: (BuildContext context, Object error, StackTrace stackTrace) {
        return const Directionality(
          textDirection: TextDirection.ltr,
          child: Text('Error is handled'),
        );
      },
    ),
  );
  await tester.pumpAndSettle();

  expect(find.text('Error is handled'), findsOneWidget);
  expect(tester.takeException(), isNull); // fails: the error also escapes as unhandled
});

Logs

In production (Flutter web, wasm), reported through runZonedGuarded with no caller frames after the async gap:

FlutterError: Unable to load asset: "assets/images/sign_in_logo.svg".
  load  flutter/packages/flutter/lib/src/services/asset_bundle.dart:332:13
  _rootRunUnary  dart-sdk/lib/async/zone_root.dart
  ...

Flutter Doctor output

Flutter 3.47.7 (stable), vector_graphics 1.2.3 (also present on main), flutter_svg 2.3.0.

Activity

  1. suryaKommana2662 commented on Oct 19, 2026

    @suryaKommana2662
    Contributor

    @mtallenca Thanks for the report. Reproduced a test failure in the vector_graphics package test suite. The asynchronous loader error is reported during VectorGraphic initialization. routing to the team-engine for further investigation

    suryakommana@SuryaKommanas-MacBook-Pro vector_graphics % flutter test test/vector_graphics_test.dart --plain-name "handles an asynchronous error from bytes loader"
    00:00 +0: handles an asynchronous error from bytes loader                                                                                                             
    ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
    The following UnimplementedError was thrown running a test:
    Test exception
    
    When the exception was thrown, this was the stack:
    #0      AsyncThrowingBytesLoader.loadBytes (file:///Users/suryakommana/develop/packages/packages/vector_graphics/test/vector_graphics_test.dart:803:5)
    #1      _VectorGraphicWidgetState._loadPicture (package:vector_graphics/src/vector_graphics.dart:371:10)
    #2      _VectorGraphicWidgetState._loadAssetBytes (package:vector_graphics/src/vector_graphics.dart:419:39)
    #3      _VectorGraphicWidgetState.didChangeDependencies (package:vector_graphics/src/vector_graphics.dart:336:15)
    #4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5981:11)
    #5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:5806:5)
    #6      Element.inflateWidget (package:flutter/src/widgets/framework.dart:4600:20)
    #7      Element.updateChild (package:flutter/src/widgets/framework.dart:4066:20)
    #8      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #9      Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #10     ProxyElement.update (package:flutter/src/widgets/framework.dart:6162:5)
    #11     _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:108:11)
    #12     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #13     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #14     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5995:11)
    #15     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #16     StatefulElement.update (package:flutter/src/widgets/framework.dart:6020:5)
    #17     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #19     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #20     ProxyElement.update (package:flutter/src/widgets/framework.dart:6162:5)
    #21     _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:108:11)
    #22     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #23     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #24     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5995:11)
    #25     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #26     StatefulElement.update (package:flutter/src/widgets/framework.dart:6020:5)
    #27     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #28     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #29     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5995:11)
    #30     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #31     StatefulElement.update (package:flutter/src/widgets/framework.dart:6020:5)
    #32     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #33     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #34     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #35     ProxyElement.update (package:flutter/src/widgets/framework.dart:6162:5)
    #36     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #37     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #38     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5995:11)
    #39     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #40     StatefulElement.update (package:flutter/src/widgets/framework.dart:6020:5)
    #41     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #42     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #43     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #44     ProxyElement.update (package:flutter/src/widgets/framework.dart:6162:5)
    #45     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #46     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #47     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #48     ProxyElement.update (package:flutter/src/widgets/framework.dart:6162:5)
    #49     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #50     _RawViewElement._updateChild (package:flutter/src/widgets/view.dart:488:16)
    #51     _RawViewElement.update (package:flutter/src/widgets/view.dart:575:5)
    #52     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #53     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #54     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #55     StatelessElement.update (package:flutter/src/widgets/framework.dart:5908:5)
    #56     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #57     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5854:16)
    #58     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5995:11)
    #59     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #60     StatefulElement.update (package:flutter/src/widgets/framework.dart:6020:5)
    #61     Element.updateChild (package:flutter/src/widgets/framework.dart:4050:15)
    #62     RootElement._rebuild (package:flutter/src/widgets/binding.dart:2091:16)
    #63     RootElement.update (package:flutter/src/widgets/binding.dart:2069:5)
    #64     RootElement.performRebuild (package:flutter/src/widgets/binding.dart:2083:7)
    #65     Element.rebuild (package:flutter/src/widgets/framework.dart:5542:7)
    #66     BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2763:15)
    #67     BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2820:11)
    #68     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3124:18)
    #69     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:2432:19)
    #70     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:558:5)
    #71     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1430:15)
    #72     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1345:9)
    #73     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:2261:9)
    #76     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
    #77     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:2250:27)
    #78     WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:598:22)
    #81     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
    #82     WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:595:27)
    #83     main.<anonymous closure> (file:///Users/suryakommana/develop/packages/packages/vector_graphics/test/vector_graphics_test.dart:778:18)
    #84     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:192:29)
    <asynchronous suspension>
    #85     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1953:5)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided 5 frames from dart:async and package:stack_trace)
    
    The test description was:
      handles an asynchronous error from bytes loader
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    00:00 +0 -1: handles an asynchronous error from bytes loader [E]                                                                                                      
      Test failed. See exception logs above.
      The test description was: handles an asynchronous error from bytes loader
      
    
    To run this test again: /Users/suryakommana/develop/flutter/bin/cache/dart-sdk/bin/dart test /Users/suryakommana/develop/packages/packages/vector_graphics/test/vector_graphics_test.dart -p vm --plain-name 'handles an asynchronous error from bytes loader'
    00:00 +0 -1: Some tests failed.   

    Flutter Doctor Output

    [✓] Flutter (Channel stable, 3.47.7, on macOS 27.0 26A428 darwin-arm64, locale en-IN) [630ms]
        • Flutter version 3.47.7 on channel stable at /Users/suryakommana/develop/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision abaf9c5237 (11 days ago), 2026-10-08 09:51:21 -0700
        • Engine revision deb287481e
        • Dart version 3.13.5
        • 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 (Android SDK version 36.0.0) [2.0s]
        • Android SDK at /Users/suryakommana/Library/Android/sdk
        • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)
        • Platform android-37.0, build-tools 36.0.0
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 25.0.2+-15348964-b329.117)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 27.1) [1,708ms]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 27A9275
        • CocoaPods version 1.17.0
    
    [✓] Chrome - develop for the web [3ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Connected device (2 available) [6.4s]
        • macOS (desktop) • macos  • darwin-arm64   • macOS 27.0 26A428 darwin-arm64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 155.0.8059.84
    
    [✓] Network resources [1,159ms]
        • All expected network resources are available.
    
    • No issues found!
  2. added
    packageflutter/packages repository. See also p: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    a: tests"flutter test", flutter_test, or one of our tests
    and removed
    in triagePresently being triaged by the triage team
    on Oct 19, 2026
  3. github-actions commented on Nov 2, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  4. locked as resolved and limited conversation to collaborators on Nov 2, 2026
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

    a: tests"flutter test", flutter_test, or one of our testshas reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: vector_graphicsThe vector_graphics package setpackageflutter/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