Skip to content

[Windows] CUA node_repl workers remain after Code Mode task completion and correlate with system-wide UI stalls #38714

Open

Description

@charonwang

Summary

On Windows, the Codex desktop app can become severely sluggish during and after a long Code Mode task that creates and repeatedly validates an interactive HTML presentation. Mouse movement and window interaction then stutter across the system, even though CPU is not saturated, disk I/O is low, and substantial physical memory remains available.

Completing the task does not reliably recover the machine. Fully exiting the Codex desktop app immediately restores normal responsiveness because it terminates the shared app-server and Code Mode runtime process tree.

Environment

  • OS: Windows 11 x64
  • Desktop app package: OpenAI.Codex_26.810.6296.0_x64
  • CUA Node runtime: cua-node 0.0.8
  • Node version: 24.19.0
  • Local app-server command includes: features.code_mode_host=true app-server --analytics-default-enabled

Reproduction

  1. Start the Windows Codex desktop app.
  2. Run a task that creates or iterates on a rich interactive HTML presentation.
  3. Ask Codex to render/inspect the page and validate desktop/mobile layout and interactions using browser or Playwright-based checks.
  4. Repeat several iterations, including interaction and responsive-layout validation.
  5. After the task reports completion, continue using the desktop app and other Windows applications.
  6. Observe severe system-wide UI and mouse stutter. Fully exit the desktop app and observe that responsiveness returns.

Observed process behavior

  • codex.exe runs the shared local app-server and owns codex-code-mode-host.exe.
  • node_repl.exe processes from the bundled cua_node runtime appear as direct children of the same app-server process.
  • The node_repl.exe count reached 37 during the affected session.
  • After the HTML task became idle/completed, 21 node_repl.exe processes plus codex-code-mode-host.exe were still present.
  • The main desktop process was approximately 1 GB working set; large renderer processes were approximately 0.6 GB and 0.2 GB.
  • The OS process command line does not expose a thread/task ID, so I cannot assign every retained child to one conversation. Some later child processes were also created while collecting diagnostics. The correlation is nevertheless strongest around the repeated HTML/browser-validation task and the shared runtime lifecycle.

Performance evidence during the lag window

  • Available memory was approximately 28--31 GB, so this did not look like simple physical-memory exhaustion.
  • Hard page reads and writes were near zero or very low; disk queue and latency were low.
  • Windows soft/transition-fault activity became extremely high, approximately 430k--470k events/sec in the worst observed samples.
  • Memory Compression was approximately 3.8--3.95 GB.
  • System CPU was only about 20--48% and was not saturated, but processor-queue spikes were observed.
  • No Application Error or Application Hang event was recorded for the session.
  • Fully exiting the desktop app terminated the shared runtime tree and immediately removed the stutter.

Expected behavior

When a Code Mode task reaches a terminal state, task-specific browser/Computer Use resources should be terminated and reaped, or a bounded shared worker pool should be reused. Multiple Codex conversations should not leave an accumulating set of runtime workers that can make the Windows desktop unresponsive.

The desktop UI should remain responsive after a task completes without requiring a full application restart.

Requested investigation

Please instrument the CUA/Code Mode spawn and cleanup lifecycle with a task/run ID, spawned PID, parent PID, terminal reason, terminate result, and wait/reap result. In particular, verify whether node_repl workers are intentionally shared, whether they are expected to survive a completed task, and whether the number of workers is bounded and reused rather than recreated per task.

If workers are task-owned, please add a regression test covering completion, cancellation, error, tool timeout, and app-server disconnect paths. If they are intentionally shared, please verify that completed tasks release their browser/runtime state and that the shared pool cannot grow without bound.

Related issues

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    on Aug 15, 2026
  2. ppg94 commented on Aug 15, 2026

    @ppg94

    Additional Windows reproduction: generated config returned, then 24 workers accumulated

    I reproduced this independently on Windows 11 (10.0.26200) with Codex Desktop 26.810.6296.0.

    A previous workaround had commented out the global node_repl MCP block. After restarting Codex, the Desktop/plugin runtime generated an active [mcp_servers.node_repl] block in config.toml again. Playwright remained disabled and its process count stayed at zero, so this recurrence was isolated from the separate Playwright MCP duplication.

    Within about 68 minutes of app-server uptime, I captured:

    • 24 live node_repl.exe processes, all direct children of the same codex.exe app-server.
    • Start times were spread across the session and tracked subsequent tool activity rather than one startup burst.
    • The 24 workers accounted for 871 threads, 3,605 handles, and about 228 MiB working set.
    • Most workers had 36 threads each; several had 38-39.
    • The broader Desktop/app-server snapshot had more than 1,100 related threads while the whole Windows UI was stuttering severely.

    I then terminated exactly those 24 workers:

    • node_repl.exe: 24 -> 0
    • The 871 worker threads and 3,605 worker handles disappeared immediately.
    • In the previous identical recurrence, terminating 16 accumulated workers immediately restored normal whole-system responsiveness; disabling the MCP block then prevented recurrence until the generated block was restored.

    After commenting out the regenerated block again, codex mcp list parsed successfully and listed no node_repl server. This workaround is therefore effective only until Desktop/plugin configuration generation re-adds the server.

    There also appears to be a separable main-process runtime-validation/read-loop regression tracked in #38518. In an earlier capture during the same investigation, the top-level ChatGPT.exe sustained about 1.14 GiB/s logical reads and ~142% of one core while physical disk/network activity was low. Killing the retained workers dramatically reduced process/thread/handle pressure and restored perceived responsiveness, but did not stop that main-process read loop during active diagnostics. This suggests the worker lifecycle leak and the main-process validation loop can coexist.

    No raw logs, session content, usernames, machine-specific paths, task identifiers, or account data are included here. I can capture a sanitized ETW trace if maintainers specify the desired providers and reproduction boundary.

  3. ppg94 commented on Aug 15, 2026

    @ppg94

    Additional lifecycle/config observation: generated block returns even when related plugins are disabled

    After a full Desktop restart with bundled chrome, browser, and computer-use plugins explicitly set to enabled = false, Desktop still regenerated an active [mcp_servers.node_repl] block and spawned 5 direct node_repl.exe workers within minutes.

    Using the documented MCP setting below was more durable than commenting/removing the generated block:

    [mcp_servers.node_repl]
    enabled = false

    After adding that field:

    • codex mcp list reported node_repl as disabled;
    • the 5 existing workers were terminated;
    • worker count remained 0 during the immediate follow-up;
    • the generated command/environment block remained present, so Desktop did not need to reconstruct missing configuration.

    This suggests the Desktop generator currently recreates the server definition independently of the three related plugin enable flags. It should preserve an explicit user-level enabled = false override and must not spawn the server when that override is present.

    No session content, account details, usernames, local paths, or raw logs are attached.

  4. smigolsmigol commented on Aug 15, 2026

    @smigolsmigol

    Additional source-level evidence from affected Windows Desktop build 26.810.4967.0 narrows the worker-retirement failure:

    • The desktop owner-retirement policy sets a one-hour inactivity TTL and a maximum of four inactive owner tasks.
    • It calculates how many owners exceed that maximum, but the returned unsubscribe candidates contain only TTL-expired IDs. The four-owner cap is therefore not enforced.
    • Tasks marked active or inProgress are excluded from TTL retirement. Stale task state can keep a runtime alive indefinitely.
    • In the affected session, 11 successful inactive-task unsubscribes reduced repeated per-task helper sets from 21 to 17. The oldest remaining repeated helper was nearly 14 hours old. No unsubscribe RPC failure or shutdown timeout was recorded.

    This is consistent with completed tasks retaining the workers reported here. A focused regression test should resume six owner tasks, leave only one active, and assert that the two oldest inactive owners unsubscribe without waiting one hour. The candidate set should include the de-duplicated union of oldest over-budget IDs and TTL-expired IDs. active and inProgress state also need a bounded work lease or watchdog.

    This evidence was initially reported in #38784. I am closing that umbrella report so worker lifecycle remains tracked here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingcomputer-useperformancewindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions