[Windows][26.727.6591.0] Avoid creating unused avatar-overlay renderer and bound renderer lifecycle

Open 💬 2 comments Opened Aug 4, 2026 by logohere

Summary

On Windows Codex Desktop, an unused avatar-overlay renderer is created during startup even when the user does not use avatars or pets. The extra renderer is small by itself, but it is an unnecessary Electron/Chromium surface and appears alongside the broader renderer/GPU memory problem.

Environment

  • Windows x64
  • Microsoft Store package: OpenAI.Codex 26.727.6591.0
  • Codex app build: 26.727.51351
  • Executable: ChatGPT.exe
  • Chromium reported by the app: 150.0.7871.182

Measurements

On a clean launch after clearing local Codex session/thread data and disposable Chromium caches:

  • Codex created 8–9 ChatGPT.exe processes.
  • Clean-launch private memory reached approximately 1.6 GB.
  • Three renderer processes were present.
  • The renderer with Electron --renderer-client-id=10 was the avatar-overlay surface and used approximately 21 MB private memory.
  • Terminating only that renderer left the main Codex window responsive, reduced the process count from 8 to 7, and produced a live snapshot of approximately 912 MB private memory / 943 MB working set.
  • A local launcher that trims only that renderer kept browser, Chrome, and computer-use features enabled.
  • Disabling browser/Chrome/computer-use plugins reduced one clean snapshot from approximately 1.63 GB to 1.25 GB, but three renderers still remained.
  • Disabling GPU acceleration made memory worse, reaching approximately 1.94 GB, so GPU disablement is not a viable workaround for this build.

These results do not prove the avatar overlay is the primary leak. They show that it is an unnecessary renderer that can be safely removed for users who do not use that feature, and that renderer/GPU lifecycle remains relevant to the larger memory issue.

Proposed solution

  1. Do not create the avatar-overlay BrowserWindow/renderer unless the avatar feature is enabled and actively needed.
  2. Treat “no avatar/pet selected” as a hard gate before creating the overlay composition surface.
  3. When the feature is hidden, dismissed, or disabled, destroy the BrowserWindow and release its webContents, IPC listeners, timers, and compositor resources instead of keeping a hidden renderer alive.
  4. Add renderer/window-appearance telemetry so memory reports identify primary, browser, and avatar-overlay surfaces.
  5. Add a bounded renderer/GPU memory regression test for a clean Windows startup and for long-running sessions.

Temporary local workaround

Fully exit all ChatGPT.exe processes and relaunch without the unused avatar overlay. Do not delete project repositories. Clearing stale session/tab state may reduce startup pressure, but it does not fix the underlying renderer memory bug.

Related issues

  • #36561 — Windows renderer repeatedly soft-restarts after rapid memory growth.
  • #35963 — Windows desktop app exits unexpectedly after memory-leak and hang events.
  • #32474 — Windows /C:/... path normalization and app-server failure.
  • #26362 — Renderer replacement while the main app/app-server remains alive.
  • #18589 — Renderer RAM runaway followed by apparent app refresh/restart.
  • #20867 — Long-thread rendering degradation on Windows.

The avatar-overlay finding is a narrower, actionable renderer-lifecycle issue that may contribute to the broader memory and hang symptoms in the linked reports.

View original on GitHub ↗

2 Comments

wukangcheng2944 · 23 days ago

Additional current-build evidence, migrated from #37073 before closing that report as a duplicate of this issue.

Environment: Codex App 26.730.61309 (build 6223), MSIX OpenAI.Codex_26.730.7989.0_x64, Windows 10.0.26200.0 x64, NVIDIA RTX 5060.

Findings from the packaged production JavaScript and live Desktop logs

  1. The hidden overlay is explicitly unthrottled. The avatarOverlay BrowserWindow is created with background throttling disabled, and the main process also calls webContents.setBackgroundThrottling(false). It mounts the common React application/bootstrap rather than a minimal pet-only surface.
  1. App-server notifications are fanned out to every registered window. The inspected broadcast path iterates all non-destroyed window listeners without filtering by appearance, visibility, focus, route, or thread interest. In one current session, the exact Reasoning summary item completed event count was 453 for the visible primary renderer and 453 for the hidden avatar overlay. The hidden overlay was logged as rendererWindowVisible=false and also processed unknown-conversation/placeholder-turn activity.
  1. The per-window chunk queue has no visible backpressure bound. ChunkedMessageSender maintains per-target criticalMessages and messages arrays. While a large transfer is waiting for renderer ACKs, subsequent messages are appended. I found no byte/count cap, stale-delta coalescing, or ACK timeout on those queues. This is a proven static risk, not a claim that the live queue length was directly measured: a slow hidden renderer can retain subsequent traffic in the Electron main process until it drains or is destroyed.
  1. The same session showed layout/jank evidence. The primary renderer logged 85 ResizeObserver loop completed with undelivered notifications errors, and the main process recorded four main_thread_jank_snapshot events. In this build the jank sampler records after approximately 900 ms or more of scheduling delay.
  1. Additional windows and the physical composition path amplify the cost. In an earlier affected build from the same investigation, a second visible primary renderer increased Codex GPU Present rate from approximately 271/s to 503/s while both windows consumed the stream. Closing the extra renderer returned the rate to baseline. On the current machine, the same session was smooth on a virtual display but laggy on the physical 275 Hz display. A controlled DWM restart reset the visible latency without terminating any of ten Codex/ChatGPT processes or producing a GPU reset; DWM resources returned near steady state after ten seconds, so this behaves like a compositor reset rather than a root fix.
  1. This current build is distinct from the older periodic WMI-sampler reports. The normal Windows sampler path in the packaged 26.730 bundle skips the periodic child-process snapshot. Tool-launched PowerShell and a one-time startup WMI call do not explain the duplicate renderer delivery above.

These findings strengthen the proposed lifecycle fix here: do not create the overlay until needed; destroy or suspend it when hidden; route only compact pet-specific state to it; and bound/coalesce every per-window IPC queue with ACK timeout and slow-target eviction.

Suggested acceptance checks:

  • A hidden overlay does not receive/render a complete streamed turn.
  • A deliberately stalled hidden renderer cannot cause unbounded Electron-main memory growth.
  • A long streamed reasoning/diff turn produces no ResizeObserver loop errors or ≥900 ms UI-thread stalls.
  • A multi-hour, multi-task Windows run keeps main/renderer memory and input latency bounded.

Related evidence: #20680 (overlay/compositor and Windows input-lag A/B), #32789 (events duplicated to primary and avatar overlay), #33996 (reasoning updates and ResizeObserver freezes), and #36561 (long-session renderer growth plus duplicate UI delivery).

l92901468-ui · 13 days ago

Additional independent reproduction on a newer Windows build (captured 2026-08-15).

Environment

  • Microsoft Store/MSIX package: OpenAI.Codex 26.810.6296.0
  • Windows 11 Pro x64, 10.0.26200
  • 8 logical processors
  • Renderer command line reported --device-scale-factor=2.5
  • The pet/overlay was tucked away: local state had electron-avatar-overlay-open=false

User-visible symptom

During a long remote Codex turn that streamed reasoning summaries, the whole desktop became periodically unresponsive and a small side bubble containing Ctrl+ repeatedly appeared. The problem cleared after fully restarting Codex, then returned during a later long streamed turn.

This was not remote compute load: the runaway was in the local Electron desktop process.

Measured impact

Before restart:

  • Electron main process: 14.84–16.80% of the whole machine, equivalent to approximately 119–134% of one logical core
  • Hottest main-process thread: approximately 81.2% of one core
  • Main-process working set: approximately 600–735 MB
  • The condition persisted while the app was otherwise usable enough to inspect

After a clean restart:

  • Electron main process: 0.43% of the whole machine / 3.4% of one core
  • Working set: approximately 297 MB
  • Desktop responsiveness returned immediately

Correlated Desktop-log evidence

In a bounded affected window (10:19–10:35 UTC), after excluding conversation text and filesystem paths:

  • Reasoning-summary events sent to visible primary renderer: 313
  • The same event class sent to hidden avatarOverlay: 313
  • Total events tagged rendererWindowAppearance=avatarOverlay rendererWindowVisible=false: 703
  • ResizeObserver loop completed with undelivered notifications: 40
  • main_thread_jank_snapshot: 106
  • unknown conversation errors: 255

The hidden surface was rendererWebContentsId=2; the visible primary surface was rendererWebContentsId=1.

A targeted experiment terminated only the later-created avatar renderer (--renderer-client-id=6). Electron immediately recreated it under a new PID, while the main process remained at 15.47% whole-machine CPU / 123.8% of one core. This suggests that killing the hidden renderer cannot recover the incident because the main-process overlay lifecycle automatically recreates it.

The packaged app also contains an avatarOverlayCpuOptimizations feature gate whose local fallback/default is false. I cannot confirm the active server-side value, so this is implementation context rather than proof of the active configuration.

Reproduction pattern

  1. Start Codex Desktop on Windows with the pet/overlay tucked away.
  2. Run a long remote task, especially one with subagent activity and frequent reasoning-summary updates.
  3. Observe that the hidden avatarOverlay still receives a 1:1 copy of the primary renderer's reasoning events.
  4. After enough streaming updates, desktop input becomes periodic/stuttery, ResizeObserver errors and main-thread jank snapshots accumulate, and the Electron main process sustains roughly one hot core.
  5. Fully restart Codex; CPU and responsiveness immediately return to baseline.
  6. Start another long streamed remote turn; the condition can recur.

This newer-build reproduction strengthens the lifecycle fix proposed in this issue:

  • Do not create or fully hydrate the avatar renderer while the overlay is tucked away.
  • Do not route complete task/reasoning streams to an invisible pet surface.
  • Suspend or destroy the surface and its listeners when hidden.
  • Add main-process recovery when the overlay/layout path enters sustained jank.
  • Enable or roll out the existing CPU-optimization path where safe.

Raw logs are intentionally not attached because they include conversation metadata. Sanitized bounded excerpts can be provided privately if maintainers request them.