Pet overlay takes 15–30s to reappear after being closed — first paint blocked on the Statsig bootstrap
What version of the Codex App are you using (From “About Codex” dialog)?
26.721.41059 (build 5848), Codex Framework 150.0.7871.128
What subscription do you have?
Plus
What platform is your computer?
Darwin 25.5.0 arm64 arm
What issue are you seeing?
Closing the pet overlay and waking it again takes 15–30 seconds on a
high-latency connection. The overlay window itself reaches ready-to-show in
~1.2s — the remaining 13–29s is spent waiting on the post-login Statsig
bootstrap (/wham/statsig/bootstrap) before the renderer mounts anything.
Everything below is from the app's own desktop logs
(~/Library/Logs/com.openai.codex/), which instrument this path end to end.
One wake, timed (2026/07/29):
07:19:00.858 [window-manager] window ready-to-show appearance=avatarOverlay
startupElapsedMs=1196 webContentsId=20
07:19:05.073 Statsig: error while bootstrapping post-login client
attemptNumber=1 errorMessage="Timed out while fetching
post-login Statsig bootstrap"
07:19:13.654 [statsig-refresh-diagnostics] ready provider mounted instanceId=1
07:19:13.968 [startup][renderer] app routes mounted after 14270ms
07:19:14.188 Native pet material attachment completed attached=true
07:19:14.188 Native pet composition presentation owned sessionId=6
Reading the gaps:
- 0 → 1.2s window created, reaches ready-to-show. Nothing drawn yet.
- 1.2 → 5.1s Statsig bootstrap runs and times out. attemptNumber=1, and no
further attempt is logged, so the timeout appears not to be
retried.
- 5.1 → 13.7s 8.6s with no Statsig log lines at all, ending in "ready provider
mounted". A second initialization path evidently ran here.
- 13.7 → 14.0s the React tree finally mounts.
- 14.0 → 14.2s native pet composition attaches and is presented. ~0.2s — not
the problem.
Two things compound:
- Every wake is a cold boot. Closing the pet tears the overlay window down
rather than hiding it. Each wake produces a new webContentsId and a complete
renderer startup sequence — there is no warm window being reused. Mount times
over six days ("app routes mounted after Nms",
rendererWindowAppearance=avatarOverlay), in ms:
1174 1426 1700 1712 1779 2113 2152 2270 2723 2811 3133 3781 4205 4207
4342 4450 4580 4998 5066 6327 7196 9516 9873 14270
Even the best case is 1.2s for re-showing a window that was open moments ago.
- First paint is gated on a feature-flag round-trip. The tree does not mount
until the Statsig provider is ready.
What steps can reproduce the bug?
- Be on a connection where backend requests are slow — anything above the
bootstrap's ~5s timeout will do. Reproduces synthetically by throttling the
overlay renderer's network (DevTools throttling, or pfctl/dummynet delay on
443). No exotic setup required.
- Open the pet overlay.
- Close it (Settings > Personalization > "Tuck Away Pet", or the overlay's
dismiss control).
- Wake it again ("Wake Pet", or "Show pet" from the command menu).
Re-clicking during the wait makes it worse: at 07:13:29–07:13:50 three overlay
windows were created in 21s (webContentsId 5, 7, 13) while I waited and
re-toggled. First window creation to "presented" was ~25s, versus ~2.7s for the
renderer that actually survived. Toggling appears to discard the partially-booted
window and start over — so the natural user response compounds the delay.
What is the expected behavior?
The pet reappears within a few hundred milliseconds. It was open moments ago,
and re-showing it should not require booting a renderer or resolving feature
flags.
Additional information
Why this connection matters — the timeout sits below its median:
Latency measured by the app's own Statsig telemetry
("[statsig-refresh-diagnostics] refresh finished durationMs=..."),
2026-07-24 → 07-29:
n = 715 min = 350ms p50 = 5028ms p90 = 23128ms max = 300020ms
For scale, DeviceCheck attestation on the same machine (local, no network) runs
at p50 17.6ms — the seconds above are entirely link time. So the ~5s bootstrap
timeout fires on most cold overlay boots rather than acting as an
exceptional-case guard. 40 "Timed out while fetching post-login Statsig
bootstrap" errors across the six-day window.
The slowness is link-wide, not host-specific. Chromium network errors in the
same window, and the paths they landed on:
69 net::ERR_NETWORK_CHANGED 38 url=/wham/tasks/list
46 net::ERR_NAME_NOT_RESOLVED 12 url=/settings/user
34 net::ERR_CONNECTION_CLOSED 9 url=/wham/usage
26 net::ERR_TIMED_OUT 4 url=/wham/statsig/bootstrap
4 net::ERR_NETWORK_IO_SUSPENDED 4 url=/wham/accounts/check
Failures are spread across many endpoints, not concentrated on the Statsig ones.
This is a general adverse-network condition, not a broken host — the network is
degraded but perfectly usable, and every other surface in the app tolerates it.
The pet is the one that becomes unusable, because it is the only surface that
pays a full cold boot on every interaction AND gates first paint on a
feature-flag round-trip.
Suggested fixes, roughly in order of value:
- Don't block first paint on the Statsig bootstrap. Render with cached or
default gate values and update when the request lands. The pet does not need
flags resolved to draw itself. This alone should take the wake from 15–30s to
roughly 1–2s.
- Hide the overlay window instead of tearing it down on close, at least for a
grace period, so wake is a show() rather than a boot. This would make it
instant.
- Bound the failure path. The bootstrap timeout does not appear to be retried,
and whatever runs afterwards took 8.6s with no apparent cap.
- Keep a warm overlay window available after a close, not just at app launch —
driven by a locally cached value, so the decision doesn't itself depend on
the network.
- Consider a leaner renderer entry point for the overlay route. It currently
boots the full app: account lookup, skills list, plugin list,
remote-connections bootstrap.
Related issues:
- #27899 — same CodexStatsigProvider gate blocking route mount on the same 5s
bootstrap timeout, but for main-window startup (4.5–6.5s). This report is the
per-interaction variant: the main window opens once per session so the cost is
amortized and stays invisible, whereas the pet pays it on every wake.
- #33713 — same anti-pattern on a different surface (in-app Browser / Chrome
extension blocked ~30s on Statsig under a slow network), which in turn
references #29385, closed as completed but still reproducible.
- #30775 — auth bootstrap failure with no retry, related to fix #3 above.
The common thread is that non-critical feature-flag traffic sits on the critical
path to first paint. Fixing that once would address all four.