Repository navigation
[Bug]: Desktop renderer polls getLocalEnvironmentBootstraps via sync IPC ~2x/s, flooding desktop traces #19505
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/desktop
Steps to reproduce
- Launch T3 Code Desktop (Linux, local primary backend only, no WSL).
- Leave it open with the sidebar visible; no interaction needed.
- Count spans in
~/.t3/userdata/logs/desktop.trace.ndjson:jq -r .name ~/.t3/userdata/logs/desktop.trace.ndjson* | sort | uniq -c | sort -rn | head
Expected behavior
The renderer learns about desktop-local backend topology changes when they happen (or polls rarely), and an idle app writes little to the desktop trace.
Actual behavior
useDesktopLocalBootstraps (apps/web/src/connection/useDesktopLocalBootstraps.ts) polls desktopBridge.getLocalEnvironmentBootstraps() every 2 s per mounted consumer (LegacySidebar, CommandPalette). That bridge call is a synchronous IPC (ipc.handleSync) and each call runs desktop.backendConfiguration.resolvePrimaryLabel, which re-reads persisted settings just to build the label.
Each poll emits four spans (desktop.ipc.invokeSync → desktop.ipc.method → desktop.ipc.window.getLocalEnvironmentBootstraps → desktop.backendConfiguration.resolvePrimaryLabel), and getLocalEnvironmentEnabled is polled alongside it. On an idle machine this is the bulk of the desktop trace:
265437 spans total (2026-10-12T02:19Z → 2026-10-14T14:30Z)
69900 desktop.ipc.method
45380 desktop.ipc.invokeSync
29963 desktop.ipc.window.getLocalEnvironmentBootstraps
29963 desktop.backendConfiguration.resolvePrimaryLabel
24520 desktop.ipc.invoke
15411 desktop.ipc.localEnvironment.getEnabled
Per-second histogram of resolvePrimaryLabel calls: 14,858 one-second buckets with exactly 2 calls, i.e. a steady ~2 calls/s for as long as the window is open. The topology never changed during that time (single primary backend, no WSL).
Effects:
- Rotated trace files fill with polling noise, crowding out useful history when debugging other problems (I hit this while investigating websocket drops).
- Sync IPC from the renderer blocks its main thread for each round trip; cheap individually (~0.1 ms handler time) but continuous and needless.
The hook's doc comment already notes the cause: "The bridge exposes no change event, so we re-read on an interval".
Suggested fix: have the desktop push a topology-changed event (the pool already knows when instances register/unregister or bootstrap tokens rotate) and let the hook subscribe, dropping the interval. Alternatively, share one poller across consumers and/or stop tracing this hot path.
Impact
Minor bug or occasional failure
Version or commit
0.0.46-nightly.20261014.3105 (also present on main @ 7ac952c)
Environment
NixOS (Linux 7.2), T3 Code Nightly desktop, Electron 44.5.1 / Chrome 152
Logs or stack traces
$ jq -r 'select(.name=="desktop.backendConfiguration.resolvePrimaryLabel") | (.startTimeUnixNano|tonumber/1e9|floor)' desktop.trace.ndjson* \
| sort | uniq -c | awk '{print $1}' | sort -n | uniq -c | sort -rn
14858 2
76 1
37 3
15 4
Activity
juliusmarminge commentedon Oct 14, 2026
Note
Grok responding on behalf of Julius.
Thanks for the trace numbers. This is the same root cause tracked in #12689: the renderer polls desktop topology (
getLocalEnvironmentBootstraps/getLocalEnvironmentEnabled) over synchronous IPC because the bridge has no change event. The triage there already names the 2 suseDesktopLocalBootstrapspoll and calls for the same fix you suggest, a topology-changed event or async reads with a cached snapshot.Open PR #19300 moves the platform poll to async
invokewith a cached snapshot. It doesn't touchuseDesktopLocalBootstraps.tsor the per-callresolvePrimaryLabelsettings read yet, so your span counts are a useful data point to add on #12689 or the PR.Closing as a duplicate of #12689 so it's tracked in one place.