Skip to content

[google_fonts] pendingFonts waits for fonts to be loaded fails ~30% of the time on Windows_x64 dart_unit_tests_shard_1; blocks any PR that runs all packages #194407

Closed
flutter/packages
#13262

Description

@okorohelijah

Summary

packages/google_fonts/test/google_fonts_text_style_test.dart: pendingFonts waits for fonts to be loaded fails on roughly 3 out of 10 runs of the Windows_x64 dart_unit_tests_shard_1 master presubmit. It only runs when a PR touches something that makes the tool run every package (.ci/, .ci.yaml, script/, Flutter rolls, ...), so it never shows up in postsubmit and it blocks exactly the PRs that can't avoid it. flutter/packages#13223 has hit it four times in a row today.

Evidence

Buildbucket history for flutter/try/Windows_x64 dart_unit_tests_shard_1 master, restricted to builds whose log contains Running for all packages and that actually ran packages/google_fonts (log: https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/<id>/+/u/Run_package_tests/dart_unit_tests/stdout?format=raw):

Month (2026) google_fonts passed failed on pendingFonts waits for fonts to be loaded
April 123 31
May 113 27
June 9 30
July 20 19
August 44 30
September 118 33
October (to the 14th) 56 27

Logs before late March don't print the per-test "Failing tests:" summary, but packages/google_fonts failures with the same shape are there every month back to January, so this is not a recent regression. There is no window where it was green.

Recent failures (all Windows_x64 dart_unit_tests_shard_1 master):

Build PR Date
8667943901072539905 flutter/packages#13223 2026-10-14
8667946301673687617 flutter/packages#13223 2026-10-14
8667946303843176033 flutter/packages#13223 2026-10-14
8667948902004693537 flutter/packages#13223 2026-10-14
8668033524488771169 flutter/packages#13241 2026-10-13
8668036604023814513 flutter/packages#13239 2026-10-13
8668039119733360769 flutter/packages#13237 2026-10-13
8668106670815314625 flutter/packages#13220 2026-10-12
8668111039808525249 flutter/packages#13197 2026-10-12
8668111728093343217, 8668113396612381169 flutter/packages#13212 2026-10-12

And the same test passing on the same builder in the same period, including once for flutter/packages#13223 itself: 8668026675852198609 (flutter/packages#13223, 2026-10-13), 8668034807642058801 (flutter/packages#13220, 2026-10-13), 8668018885495354161 (flutter/packages#13243, 2026-10-13). Bots are fresh VMs each time, so it is not tied to a particular machine. Linux dart_unit_test_shard_* runs the same test and has been green throughout; there is no macOS dart unit test builder for this repo.

What actually fails

The CI log never contains an [E] block for this test. What it does show is the pass counter going down by one at the moment the failure is counted, e.g. build 8667943901072539905:

00:03 +92: .../google_fonts/test/generated_font_methods_test.dart: getFont works with all fonts in GoogleFonts.asMap
00:03 +91 -1: .../google_fonts/test/generated_font_methods_test.dart: getFont works with all fonts in GoogleFonts.asMap
...
Failing tests:
  C:/b/s/w/ir/x/w/packages/packages/google_fonts/test/google_fonts_text_style_test.dart: pendingFonts waits for fonts to be loaded

That is the signature of a test that passed and was then marked failed by an error that arrived after it had completed (171 of the 202 failing logs since March show the same +N to +N-1 drop; the rest are interleaved with other suites' progress lines).

The source of that late error is reproducible by keeping the test alive for a couple of seconds after its last expect:

pendingFonts flow plus a wait for late errors [E]
  MissingPluginException(No implementation found for method getApplicationSupportDirectory on channel plugins.flutter.io/path_provider)
  package:flutter/src/services/platform_channel.dart 363:7        MethodChannel._invokeMethod
  ===== asynchronous gap ===========================
  package:google_fonts/src/file_io_desktop_and_mobile.dart 26:21  saveFontToDeviceFileSystem
  package:google_fonts/src/google_fonts_base.dart 265:15          _httpFetchFontAndSaveToDevice
  ===== asynchronous gap ===========================
  package:google_fonts/src/google_fonts_base.dart 168:18          loadFontIfNecessary
  package:google_fonts/src/google_fonts_base.dart 107:38          googleFontsTextStyle

Sequence:

  1. The test calls googleFontsTextStyle for two families (ab, cd) with a mock HTTP client and awaits GoogleFonts.pendingFonts() twice. All three expects pass on every platform; pendingFontFutures bookkeeping is fine.
  2. _httpFetchFontAndSaveToDevice (lib/src/google_fonts_base.dart) fires file_io.saveFontToDeviceFileSystem(...) and deliberately drops the future (_unawaited). The future returned by loadFontIfNecessary only waits for FontLoader.load(), not for that write.
  3. The test does not fake PathProviderPlatform, so getApplicationSupportDirectory() fails with MissingPluginException, once per family, inside the dropped future. Nothing catches it, so it becomes an uncaught asynchronous error in the test's zone.
  4. The method channel reply comes back after the test body has already finished. This file has a single test, so by then the suite is being torn down. On Linux the teardown consistently wins and the error is lost silently (test passes). On Windows the error regularly lands while the runner is still attached, which flips the already-passed test to failed ("This test failed after it had already completed"). The detailed [E] output is not in the CI logs, presumably because the runner closes the test between the state change and the error message.

So: the product code is doing what it does in any app (write the font to the application support directory in the background); the test is the problem, because it exercises the HTTP path on a desktop VM without giving path_provider an implementation. load_font_if_necessary_test.dart in the same package already installs a FakePathProviderPlatform pointing at a temp directory, which is why it does not have this problem.

Why postsubmit never catches it

Postsubmit only tests the packages touched by each commit; google_fonts is rarely touched. Presubmits for PRs that change repo-wide files run every package (Running for all packages, since a file has changed that could affect the entire repository.) and are the only place this test runs on Windows.

Activity

  1. added
    packageflutter/packages repository. See also p: labels.
    P1High-priority issues at the top of the work list
    c: flakeTests that sometimes, but not always, incorrectly pass
    p: google_fontsPackage to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling.
    and removed
    P1High-priority issues at the top of the work list
    on Oct 14, 2026
  2. stuartmorgan commented on Oct 15, 2026

    @stuartmorgan
    Contributor

    Postsubmit only tests the packages touched by each commit; google_fonts is rarely touched. Presubmits for PRs that change repo-wide files run every package

    Presubmit and postsubmit do not behave differently in this regard; a PR that touches a repo-wide file runs every package's tests in both presubmit and postsubmit.

  3. github-actions commented on Oct 29, 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 Oct 29, 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

    c: flakeTests that sometimes, but not always, incorrectly passp: google_fontsPackage to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling.packageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions