Skip to content

engine: explain why each candidate build was skipped in Flutter web loader#186254

Merged
auto-submit[bot] merged 9 commits into
flutter:masterfrom
shivanshu877:feat/wasm-loader-explain-fallback-v2
Jul 8, 2026
Merged

engine: explain why each candidate build was skipped in Flutter web loader#186254
auto-submit[bot] merged 9 commits into
flutter:masterfrom
shivanshu877:feat/wasm-loader-explain-fallback-v2

Conversation

@shivanshu877

@shivanshu877 shivanshu877 commented May 8, 2026

Copy link
Copy Markdown
Contributor

Description

When the Flutter web loader picks a build for the current browser, it walks buildConfig.builds and takes the first one whose compileTarget, renderer, and WASM-allowlist constraints all match. Today, builds that fail those checks are silently filtered out, so:

  • If every build is rejected, the user sees the generic "FlutterLoader could not find a build compatible..." error and has no way to tell which constraint blocked which build.
  • If a preferred build (e.g. dart2wasm + skwasm) is rejected and the loader silently falls back to a less-preferred build (e.g. dart2js + canvaskit), the user has no way to tell that a fallback even happened, much less why.

This was suggested by @yjbanov in #143603 (comment) and is the fallback-side complement to the COOP/COEP load-failure warning in #142822.

What changed

loader.js's buildIsCompatible was a bool-returning predicate. Refactored to buildIncompatibilityReason that returns either null (compatible) or a short human-readable string. The selection loop captures the reason for each skipped candidate, then:

  • If no compatible build is found, prints a console.warn unconditionally so the silently-blank-page case is never silent. The warning hints at verboseBuildSelection for follow-up.
  • If verboseBuildSelection: true is set on the Flutter config, prints one console.warn per skipped candidate explaining its rejection reason — useful both for the no-build case and for the "why does the loader keep falling back to canvaskit when I expected skwasm?" debug case. Off by default to keep the typical user's console quiet.

Sample output a developer would see on a browser without WasmGC, with verboseBuildSelection: true:

[warn] Flutter Web: build dart2wasm/skwasm was skipped: dart2wasm requires WasmGC support; this browser does not implement it yet.

And without verboseBuildSelection, when no compatible build is found:

[warn] Flutter Web: no compatible build found for this browser. Set `verboseBuildSelection: true` in your Flutter configuration to see why each candidate was rejected.

Tests

No JS test infrastructure exists for engine/src/flutter/lib/web_ui/flutter_js/. The change is also pure additive logging — the build-selection algorithm picks the same build it picked before. Requesting a test exemption.

This PR replaces #186238 (closed for a clean conversation timeline).

Pre-launch Checklist

…oader

When the Flutter web loader picks a build for the current browser, it
walks `buildConfig.builds` and takes the first one whose compileTarget,
renderer and WASM-allowlist constraints all match. Today, builds that
fail those checks are silently filtered out, so:

* If every build is rejected, the user sees the generic "FlutterLoader
  could not find a build compatible..." error and has no way to tell
  which constraint blocked which build.
* If a preferred build (e.g. dart2wasm + skwasm) is rejected and the
  loader silently falls back to a less-preferred build (e.g. dart2js +
  canvaskit), the user has no way to tell that a fallback even
  happened, much less why.

Refactor the compatibility check to return either `null` (compatible)
or a short human-readable reason. Use that to:

* Print a `console.warn` for each skipped build when no compatible
  build is found, before throwing the existing error.
* Print a single `console.info` summarizing skipped candidates when
  the loader falls back from a preferred build to a later one.

Co-addresses the diagnostic gap discussed in
flutter#143603 and is the
fallback-side complement to the COOP/COEP warning in
flutter#142822.
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-web Web applications specifically labels May 8, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the Flutter Web loader by replacing boolean compatibility checks with detailed incompatibility reasons. It introduces logging to explain why specific builds are rejected or when the loader falls back to an alternative build. Review feedback suggests improving the readability of log messages by avoiding JSON.stringify on objects and recommends throwing Error objects instead of string literals to provide better debugging context via stack traces.

Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
@gaaclarke gaaclarke added the team-web Owned by Web platform team label May 11, 2026
@kevmoo

kevmoo commented May 12, 2026

Copy link
Copy Markdown
Contributor

My first thought: I'd rather see this as an option that can be enabled by the app author to debug. Not on by default.

@shivanshu877

Copy link
Copy Markdown
Contributor Author

Thanks for taking a look, @kevmoo! Happy to make this opt-in.

One nuance worth clarifying: there are two log paths and they have different cost/value trade-offs:

  1. console.warn per skipped build — fires only on the error path (no compatible build found; load is about to throw the existing "FlutterLoader could not find a build compatible…" error). Since the load fails regardless, the warns are diagnostic context for a fatal error.
  2. console.info summary — fires on the success path when a preferred build was skipped and a later one was used (e.g. dart2wasm→canvaskit fallback on a browser without WasmGC). This one is the more opinionated production noise.

Two questions:

  • Should both paths be gated, or just the console.info fallback notification?
  • For the opt-in mechanism, would a debugBuildSelection: true property on FlutterLoader.loadEntrypoint({ config }) be the right place, or do you prefer a different convention (build-mode check, URL query param, etc.)?

Happy to follow whatever the team prefers.

@flutter-zl
flutter-zl requested a review from harryterkelsen May 13, 2026 18:14

@harryterkelsen harryterkelsen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR: Let's keep the warnings when no build is found and remove the infos when the preferred build is skipped

I think we should keep the console.warn messages for the case where no valid build can be found, because in that case we only get a blank screen and a console warning anyways, so more information is definitely better here.

For the case where the "preferred" builds are skipped, I don't know if it's worth keeping those console.info messages. I think we can land the extra logs for the case where no build is found but I worry that the "per-build" logs for the case where we fall back to a different build than the one requested is overly verbose.

For example, if I say I want to use a WASM/Skwasm build but it falls back to Dart2js/Canvaskit because the page is running on Safari, I don't think we should have a separate line for each skipped build, since it is likely that each skipped build will just have the same reason for being skipped. The app developer may even "expect" that on Safari it falls back to Dart2js/CanvasKit and doesn't want users to see a "scary" info message in the console saying that all these builds were rejected.

Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
Comment thread engine/src/flutter/lib/web_ui/flutter_js/src/loader.js Outdated
…y reasons

Per harryterkelsen review on flutter#186254:
- Remove the console.info block that logged a success-path fallback summary.
  The console.warn messages on the fatal "no compatible build" path are kept.
- Inline the compound supportsSkwasm check into two separate conditions
  (WasmGC, then WebGL) so each incompatibility reason is specific.
@github-actions github-actions Bot removed the team-web Owned by Web platform team label May 15, 2026
Use compileTarget/renderer string instead of JSON.stringify for cleaner
console output; throw an Error object so the stack trace is captured.
@gaaclarke gaaclarke added the team-web Owned by Web platform team label May 18, 2026
@shivanshu877

Copy link
Copy Markdown
Contributor Author

Thanks @harryterkelsen — done! The current branch state matches your TLDR exactly:

  • Kept: the per-skipped-build console.warn in the "no compatible build found" path (line 134-138 of loader.js).
  • Removed: the console.info summary that fired on the success-fallback path — gone, no longer logs when a preferred build is skipped but a later one matches.

So Safari users falling back from dart2wasm/skwasm to dart2js/canvaskit won't see any "scary" extra info messages anymore; they'll only see the console.warn block if literally no build can be used at all.

Bonus: also switched the existing throw "…" to throw new Error("…") so the stack trace is preserved.

Re-pinging for review (the changes-requested label should be safe to dismiss now). The diff is small enough to eyeball — let me know if anything still feels off.

harryterkelsen
harryterkelsen previously approved these changes May 22, 2026

@harryterkelsen harryterkelsen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@harryterkelsen harryterkelsen added engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team CICD Run CI/CD and removed engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team labels May 22, 2026
@harryterkelsen

Copy link
Copy Markdown
Contributor

Thanks, @shivanshu877!

@harryterkelsen harryterkelsen added CICD Run CI/CD and removed CICD Run CI/CD labels Jun 1, 2026
@github-actions github-actions Bot removed the team-web Owned by Web platform team label Jun 1, 2026
@harryterkelsen harryterkelsen added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 2, 2026

@eyebrowsoffire eyebrowsoffire left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for the fix!

@eyebrowsoffire eyebrowsoffire added the CICD Run CI/CD label Jun 16, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 24, 2026
@harryterkelsen harryterkelsen added the CICD Run CI/CD label Jun 24, 2026
b-luk pushed a commit to b-luk/flutter that referenced this pull request Jul 1, 2026
…ontributor PRs (flutter#188534)

## Description

This Pull Request adds the `shepherd-prs` skill to the repository. The
skill is designed to help agentic coding assistants automate the
shepherding and landing of approved third-party Pull Requests in the
`flutter/flutter` repository.

Under the hood, it utilizes a self-contained, type-safe Dart
command-line tool (`scripts/shepherd.dart`) that interacts with the
GitHub and LUCI APIs via the `gh` CLI. It identifies approved PRs,
checks their CI health and branch states, and performs necessary
maintenance tasks (like branch updates and CI trigger re-runs) before
safe integration.

---

## Skill Usage Examples

Below are examples of user prompts, the agent's internal tool
executions, and the resulting outputs:

### Example 1: Retrieving and Summarizing PR Status

**User Prompt:**
> "What is the status of my approved PRs?"

**Agent Execution:**
The agent loads the skill, executes the read-only list command, and
parses the JSON response:
```bash
dart .agents/skills/shepherd-prs/scripts/shepherd.dart list
```

**Agent Response:**
> You have 1 approved third-party PR requiring shepherding:
> 
> * **PR flutter#186254**: *Fix web image codec unification issues* (by
@External-Contributor)
>   - **Status**: Clean of conflicts, all 4 CI checks passed.
>   - **Branch State**: Behind the default branch by 52 commits.
> - **Recommended Action**: Update branch (bring up to date with
`main`).
> 
> Would you like me to execute the branch update for PR flutter#186254?

---

### Example 2: Running Shepherding on a Specific PR

**User Prompt:**
> "Yes, please update the branch for PR flutter#186254."

**Agent Execution:**
Upon receiving explicit user confirmation, the agent runs the execution
command:
```bash
dart .agents/skills/shepherd-prs/scripts/shepherd.dart run --pr 186254
```

**Agent Response:**
> I have successfully triggered the branch update for **PR flutter#186254**
(was behind by 52 commits). I will monitor the PR and let you know when
the update is complete and CI starts running.


## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Jul 7, 2026
@harryterkelsen harryterkelsen added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Jul 7, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jul 8, 2026
Merged via the queue into flutter:master with commit 015ea6d Jul 8, 2026
207 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 8, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jul 10, 2026
…12169)

Manual roll Flutter from 91939cc4db78 to dc2a8703e12b (50 revisions)

Manual roll requested by [email protected]

flutter/flutter@91939cc...dc2a870

2026-07-09 [email protected] [ios,macos] Update swiftc.py flags to match swiftc (flutter/flutter#189174)
2026-07-09 [email protected] [AGP 9] Update Warn Version to AGP 9+ (flutter/flutter#189109)
2026-07-09 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#189203)
2026-07-09 [email protected] [web] Roll Chrome to 145 (framework) (flutter/flutter#182861)
2026-07-09 [email protected] Roll Packages from 52d84d6 to 20928d5 (6 revisions) (flutter/flutter#189194)
2026-07-09 [email protected] [web] Avoid absolute positioning for base CanvasKit canvas (flutter/flutter#188337)
2026-07-09 [email protected] Roll Dart SDK from cdb7217e65aa to a11fb7ed40a5 (6 revisions) (flutter/flutter#189195)
2026-07-09 [email protected] Fix dereference of nullptr in the moved-to-rect signal in the Linux embedder (flutter/flutter#189152)
2026-07-09 [email protected] Fix data for design packages (flutter/flutter#189140)
2026-07-09 [email protected] Roll Skia from 7b42d1251d54 to ab3a7b98c94d (2 revisions) (flutter/flutter#189181)
2026-07-09 [email protected] Roll Skia from 05d9d214e0b7 to 7b42d1251d54 (2 revisions) (flutter/flutter#189175)
2026-07-09 [email protected] Roll Skia from 542c8bdd7f4f to 05d9d214e0b7 (4 revisions) (flutter/flutter#189169)
2026-07-09 [email protected] UberSDF rect handling for thin (line-like) rectangles (flutter/flutter#188821)
2026-07-09 [email protected] Roll Skia from dd572c07f63c to 542c8bdd7f4f (4 revisions) (flutter/flutter#189160)
2026-07-09 [email protected] [flutter_tools] Fix hot restart for WASM web builds (flutter/flutter#187898)
2026-07-08 [email protected] Split FlViewRenderer into OpenGL and software backends (flutter/flutter#188824)
2026-07-08 [email protected] Promote android_hardware_smoke_tests out of bringup in CI (flutter/flutter#189081)
2026-07-08 [email protected] Roll Skia from 8df24be66531 to dd572c07f63c (4 revisions) (flutter/flutter#189150)
2026-07-08 [email protected] Expose LinuxWindowRegistrar on _window_linux.dart in order to better support out of tree LinuxWindowingOwners (flutter/flutter#188917)
2026-07-08 [email protected] Roll pub packages (flutter/flutter#189149)
2026-07-08 [email protected] fix(ci): harden some workflows (flutter/flutter#189087)
2026-07-08 [email protected] Roll Skia from 51a62da33da0 to 8df24be66531 (1 revision) (flutter/flutter#189139)
2026-07-08 [email protected] Roll Dart SDK to Dart 3.13 beta3 (flutter/flutter#189122)
2026-07-08 [email protected] [flutter_tools] Don't crash on non-UTF-8 plugin pubspec.yaml (flutter/flutter#188976)
2026-07-08 [email protected] [flutter_tools] Watch transitive #include headers for FragmentProgram hot reload (flutter/flutter#187945)
2026-07-08 [email protected] Roll Skia from 040d9f55de00 to 51a62da33da0 (1 revision) (flutter/flutter#189135)
2026-07-08 [email protected] Roll Packages from 92525f5 to 52d84d6 (7 revisions) (flutter/flutter#189134)
2026-07-08 [email protected] [flutter_tools] Forcefully kill hung subprocesses 5 seconds after timeout (flutter/flutter#187178)
2026-07-08 [email protected] Expose the app's build name and number as compile-time constants (flutter/flutter#187935)
2026-07-08 [email protected] Roll Skia from 1ff92f879815 to 040d9f55de00 (1 revision) (flutter/flutter#189131)
2026-07-08 [email protected] Roll Skia from 6137414bef5c to 1ff92f879815 (6 revisions) (flutter/flutter#189126)
2026-07-08 [email protected] [test cross imports] More test/rendering + flutter_test/test fixes (flutter/flutter#188954)
2026-07-08 [email protected] engine: explain why each candidate build was skipped in Flutter web loader (flutter/flutter#186254)
2026-07-08 [email protected] vscode: add missing unicode.h (flutter/flutter#189102)
2026-07-08 [email protected] Roll Fuchsia Linux SDK from 7RjQJBW3m-3Jl-7jr... to QcRFUtvCw2EobfJ8s... (flutter/flutter#189104)
2026-07-08 [email protected] Roll Skia from 075fbe4778d9 to 6137414bef5c (10 revisions) (flutter/flutter#189106)
2026-07-08 [email protected] engine: warn on WASM load failure when not crossOriginIsolated (flutter/flutter#186252)
2026-07-08 [email protected] Roll Dart SDK from c9bccc09e733 to db2155f56bf3 (2 revisions) (flutter/flutter#189105)
2026-07-08 [email protected] [flutter_tools] Prevent interactive device selection in machine mode (flutter/flutter#188267)
2026-07-08 [email protected] [flutter_tools] Fix wireless ADB device discovery when serial contains spaces (flutter/flutter#187943)
2026-07-07 [email protected] [web] Fix grouped autofill on iOS Chrome (flutter/flutter#187459)
2026-07-07 [email protected] Fix TextSelectionOverlay crash when layout is degenerate (flutter/flutter#188672)
2026-07-07 [email protected] [flutter_tools] Provision Android NDK in the main Gradle invocation (flutter/flutter#186337)
2026-07-07 [email protected] Android_hardware_smoke_test: Migrate to AGP 9 (flutter/flutter#189082)
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants