Skip to content

[google_font] pendingFonts() fails indefinitely after a single failed font loading #182430

Closed
flutter/packages
#12240

Description

@bramp

Steps to reproduce

The google_fonts library tracks ongoing font loads in a global Set<Future<void>> pendingFontFutures. This set is used by GoogleFonts.pendingFonts() to await all active requests. In the current implementation, futures are removed from this set using .then(...). However, in Dart, the .then callback only executes on successful completion. If a font load fails (e.g., due to a 404 error or network timeout), the future is never removed from the set.

Since GoogleFonts.pendingFonts() performs a Future.wait() on the entire set, it will immediately re-throw the original error every time it is called, as long as the failed future remains in memory. This leads to "poisoned" states where a single failure breaks all subsequent font synchronization.

  1. Trigger a background font load that is guaranteed to fail (e.g., using a mock client that returns an error).
  2. Await GoogleFonts.pendingFonts() and catch the exception.
  3. Call GoogleFonts.pendingFonts() a second time.

The fix is to use

// In lib/src/google_fonts_base.dart
// Change this:
loadingFuture.then((_) => pendingFontFutures.remove(loadingFuture));

// To this:
loadingFuture
    .whenComplete(() => pendingFontFutures.remove(loadingFuture))
    .catchError((_) {});

Expected results

The second call to pendingFonts() should succeed (or return a new set of results) because the previously failed load has finished and should have been cleared.

Actual results

The second call (and all subsequent calls) immediately throws the original exception because the failed future is still present in the tracking set.

Code sample

Code sample

Because we can't mock the http client from outside the package, this is not a flutter create bug but instead a test case inside the package:

test('pendingFonts() cleans up failed futures', () async {
    await overridePrint(() async {
      // Mock a failure.
      when(mockHttpClient.gets(any)).thenThrow(Exception('Network failure'));

      // Trigger a font load.
      GoogleFonts.abel();

      // The first call to pendingFonts() should throw the error.
      try {
        await GoogleFonts.pendingFonts();
        fail('Should have thrown');
      } catch (e) {
        expect(e.toString(), contains('Network failure'));
      }

      // BUG: If fixed with .whenComplete, pendingFontFutures should be empty now.
      // If using .then, the failed future is still there.
      expect(
        pendingFontFutures,
        isEmpty,
        reason: 'failed futures should be removed from the pending set',
      );

      // Subsequent calls will now throw the exception, forever.
      await GoogleFonts.pendingFonts();
    });
  });

Screenshots or Video

Screenshots / Video demonstration

N/A

Logs

Logs

N/A

Flutter Doctor output

Doctor output
❯ flutter doctor -v
[✓] Flutter (Channel stable, 3.41.0, on macOS 26.2 25C56 darwin-arm64, locale en-GB) [356ms]
    • Flutter version 3.41.0 on channel stable at /opt/homebrew/share/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 44a626f4f0 (4 days ago), 2026-02-10 10:16:12 -0800
    • Engine revision 3452d735bd
    • Dart version 3.11.0
    • DevTools version 2.54.1
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, omit-legacy-version-file,
      enable-lldb-debugging, enable-uiscene-migration

[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [2.1s]
    • Android SDK at /Users/bramp/Library/Android/sdk
    • Emulator version 36.3.10.0 (build_id 14472402) (CL:N/A)
    ✗ Flutter requires Android SDK 36 and the Android BuildTools 28.0.3
      To update the Android SDK visit https://flutter.dev/to/macos-android-setup for detailed instructions.
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS (Xcode 26.2) [985ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17C52
    ! iOS 26.2 Simulator not installed; this may be necessary for iOS and macOS development.
      To download and install the platform, open Xcode, select Xcode > Settings > Components,
      and click the GET button for the required platform.

      For more information, please visit:
        https://developer.apple.com/documentation/xcode/installing-additional-simulator-runtimes
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [6ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Connected device (2 available) [6.3s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 26.2 25C56 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 145.0.7632.75

[✓] Network resources [315ms]
    • All expected network resources are available.

! Doctor found issues in 2 categories.

Activity

  1. saurabh-mirajkar commented on Feb 20, 2026

    @saurabh-mirajkar
    Contributor

    @bramp Thanks for a detailed report. Labelling it for further investigation.

  2. added
    p: material_uimaterial_ui package in flutter/packages
    packageflutter/packages repository. See also p: labels.
    p: google_fontsPackage to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling.
    and removed
    in triagePresently being triaged by the triage team
    on Feb 20, 2026
  3. added
    P2Important issues not at the top of the work list
    on Feb 24, 2026
  4. assigned and unassigned on Feb 24, 2026
  5. added a commit that references this issue on Jul 31, 2026
    ac87e65
  6. github-actions commented on Aug 15, 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.

  7. locked as resolved and limited conversation to collaborators on Aug 15, 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

    P2Important issues not at the top of the work listp: google_fontsPackage to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling.p: material_uimaterial_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions