Found while measuring #2628. Different window, independent of that card — #2628 is the gap beforeLoadingScreen mounts; this one is a fully-white frame that appears after it has already painted, and it survives the #2628 fix.
What was measured
Production build of apps/console, served locally with the two boot endpoints mocked, driven by Playwright with CDP Page.startScreencast at everyNthFrame: 1. Every captured frame decoded and classified pixel-by-pixel (a frame counts as white when no colour channel falls below 242). Timestamps are relative to performance.timeOrigin.
The frame ledger of one run on f53a8d0ae, unthrottled localhost:
t=27ms nonWhite=0% min=255 [ the #2628 window ]
t=165ms nonWhite=0% min=246
t=1527ms nonWhite=2.349% min=0 [ LoadingScreen paints ]
t=1544ms nonWhite=2.350% min=0
t=1567ms nonWhite=0% min=246 [ fully white again, one frame ]
t=1681ms nonWhite=1.387% min=0 [ content returns ]
How often
Counting only frames after the first contentful frame, over full-boot runs (the instrument waits for React's first commit, so the whole boot is sampled) — same instrument on both sides, 3 runs per cell:
| profile | pre-#2628-fix build | post-fix build |
|---|
| localhost, no throttling | 0 / 3 | 2 / 3 |
| 20 Mbps / 80 ms RTT | 2 / 3 | 1 / 3 |
| Fast 4G (4 Mbps / 70 ms) | 2 / 3 | 0 / 3 |
| total | 4 / 9 | 3 / 9 |
Gap length 40-230 ms.
⚠️n=9 per side does not distinguish 4/9 from 3/9 — read this as "roughly one boot in three, before and after", not as an improvement or a regression. A separate earlier pre-fix set of 11 runs that stopped shortly after first paint (a shorter tail, so a different sampling window — deliberately not pooled with the above) hit 6/11.
That the rate is unchanged by the #2628 fix is expected: that fix covers the window before React's first commit and its indicator is already removed by the time this happens.
What is NOT established
- The cause. The obvious suspects are
LoadingScreen unmounting before the replacing view has painted, or RouteFader (packages/app-shell/src/chrome/RouteFader.tsx) — but nothing here correlates the frame with a DOM state, so both are guesses. Whoever picks this up should timestamp the DOM alongside the frames rather than start from either name. - Whether a user notices. A 40-230 ms full-viewport white flash mid-boot reads as a flicker rather than a blank page. Severity is a triage call, not a measurement.
Why it is filed rather than fixed
#2628 was scoped by triage to tier 1 — the pre-LoadingScreen window only — and explicitly told the dev to file anything else instead of widening. This is that.
The repro harness (server + screencast classifier) is not committed anywhere; it is described in full in the #2628 pull request, and e2e/console-boot-indicator.spec.ts landed there carries the Playwright-side scaffolding a fix for this could extend.
Found while measuring #2628. Different window, independent of that card — #2628 is the gap before
LoadingScreenmounts; this one is a fully-white frame that appears after it has already painted, and it survives the #2628 fix.What was measured
Production build of
apps/console, served locally with the two boot endpoints mocked, driven by Playwright with CDPPage.startScreencastateveryNthFrame: 1. Every captured frame decoded and classified pixel-by-pixel (a frame counts as white when no colour channel falls below 242). Timestamps are relative toperformance.timeOrigin.The frame ledger of one run on
f53a8d0ae, unthrottled localhost:How often
Counting only frames after the first contentful frame, over full-boot runs (the instrument waits for React's first commit, so the whole boot is sampled) — same instrument on both sides, 3 runs per cell:
Gap length 40-230 ms.
That the rate is unchanged by the #2628 fix is expected: that fix covers the window before React's first commit and its indicator is already removed by the time this happens.
What is NOT established
LoadingScreenunmounting before the replacing view has painted, orRouteFader(packages/app-shell/src/chrome/RouteFader.tsx) — but nothing here correlates the frame with a DOM state, so both are guesses. Whoever picks this up should timestamp the DOM alongside the frames rather than start from either name.Why it is filed rather than fixed
#2628 was scoped by triage to tier 1 — the pre-
LoadingScreenwindow only — and explicitly told the dev to file anything else instead of widening. This is that.The repro harness (server + screencast classifier) is not committed anywhere; it is described in full in the #2628 pull request, and
e2e/console-boot-indicator.spec.tslanded there carries the Playwright-side scaffolding a fix for this could extend.