[Desktop/macOS] Renderer freezes after referencing large local Codex chats while backend tasks continue

Open 💬 1 comment Opened Jul 21, 2026 by angjelkom
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Codex Desktop on macOS becomes completely non-interactive after using the @ mention interface to reference large existing local Codex chats.

When this happens, mouse and keyboard input stop working, but per-task spinners remain animated and background tasks continue running. Tasks can complete successfully while the window remains frozen. Force-quitting and reopening temporarily restores access, but reopening the reference-heavy task can freeze the renderer again.

This appears to be a desktop renderer responsiveness failure rather than a model, network, app-server, database, or filesystem-search failure.

Environment

  • Codex Desktop: 26.715.61943
  • Desktop build: 5628
  • Bundled Codex backend: 0.145.0-alpha.27
  • Chromium/Electron framework: 150.0.7871.124
  • OS: macOS 26.5.1, arm64

Steps to reproduce

  1. Create or identify two long local Codex chats with substantial histories.
  2. Start a new Codex task.
  3. Type @ in the composer and select both existing chats as references.
  4. Submit a short request.
  5. Optionally leave other tasks streaming in the background.
  6. Navigate away from the new task and then reopen or resume it.

A related UI stall has also been observed while searching for files or chats through the @ menu while other tasks are streaming.

Actual behavior

  • The desktop renderer stops servicing user input.
  • The native application process and bundled app-server remain alive.
  • Background task output continues to be generated for the connected desktop client.
  • Turn-completion events are generated but are not reflected by the frozen window.
  • Reopening the affected task can reproduce the freeze.
  • No renderer crash dialog, fatal error, panic, or out-of-memory termination is produced.

Expected behavior

  • Referencing a large chat must not block the desktop renderer.
  • Large references should be bounded, summarized, truncated, or loaded lazily.
  • The @ result menu should remain responsive while its result sources update.
  • Background streaming events should not starve input handling.
  • Completed or interrupted turns should not remain marked as streaming.
  • If a reference exceeds a supported limit, the app should reject it recoverably rather than persisting a task that freezes when reopened.

Sanitized investigation results

Reference expansion

The reproduction referenced two local Codex chats containing 325 and 118 conversation items, or 443 embedded items in total.

The generated context contained:

  • 456,237 characters of serialized reference data
  • 456,662 characters in the complete generated user-context record
  • 312 characters in the actual user request

The reference data was represented as one extremely long serialized line. It was persisted in two event representations, accounting for approximately 0.92 MB of a 1.25 MB task record.

Across the inspected local session corpus, reference payloads frequently reached tens or hundreds of thousands of characters. This 456k-character payload was the largest observed.

Packaged reference serializer

Inspection of the packaged renderer shows the referenced-chat collection being appended using the equivalent of JSON.stringify(threadReferences). There is no character, byte, or item budget at that serialization point. The captured payload demonstrates that at least 443 conversation items can reach it without truncation.

There may be limits elsewhere in the system, but they did not prevent this reproduction.

Backend loading and state

For the affected task:

  • thread/read completed in approximately 14 ms.
  • thread/resume completed in approximately 195 ms.
  • The backend described the latest turn as interrupted while renderer-side state still marked the task as streaming.

This suggests the freeze is not caused by slow session storage or thread loading. The interrupted/streaming state mismatch may also explain persistent spinner state.

Work continued after the renderer stalled

After the UI stopped responding, the same bundled backend process produced approximately:

  • 2,000 additional diagnostic records
  • 348 agent-text delta events
  • 246 command-output delta events
  • Peaks of 58 agent-text deltas per second

Events were still directed toward one connected desktop client. The active turn later completed successfully, and no new deltas followed, but the window remained unusable.

@ menu behavior

A non-empty @ query can concurrently update file, existing-chat, plugin, skill, application, and agent results. File and chat searches are debounced by approximately 100 ms, and chat search can return up to 50 results before the sections are merged.

The result menu preserves its highlighted item while sections change and remeasures layout using ResizeObserver plus animation frames. The observer watches both the menu element and the document root.

Captured fuzzy-file-search requests completed in 0-87 ms. This makes filesystem search itself an unlikely cause of file-related stalls; result reconciliation or layout is a more likely bottleneck.

Renderer layout churn

Two desktop sessions emitted repeated ResizeObserver loop completed with undelivered notifications warnings:

  • 841 occurrences in one session
  • 178 occurrences in the following session

The warnings arrived in bursts around chat navigation, streaming updates, and task switching. The packaged app excludes this warning from Sentry, so it is treated here as evidence of layout churn rather than proof of the root cause.

Logging and disk-write pressure

Additional generic diagnostics:

  • The local diagnostic SQLite log database was approximately 405 MB with about 205,000 records.
  • A macOS resource report recorded approximately 2.15 GB written by the bundled backend over 4,745 seconds; SQLite writes appeared in the heaviest sampled stack.
  • A separate desktop-process report recorded approximately 2.15 GB written over 3,683 seconds and a maximum footprint of approximately 515 MB.

This may not be the primary renderer lock, but high-volume trace logging and SQLite writes appear to reduce available performance headroom.

Checks that passed

The following were verified and do not appear to explain the freeze:

  • OpenAI endpoint reachability
  • Responses WebSocket handshake
  • Authentication configuration
  • Main state-database integrity
  • Diagnostic log-database integrity
  • Session-rollout and state-database parity
  • Saved-thread inventory consistency
  • Auxiliary database integrity using immutable read-only checks
  • Filesystem fuzzy-search response time

There was no evidence of a renderer crash, render-process-gone, fatal error, panic, out-of-memory termination, model/API outage, or corrupted task record.

Suspected cause

The strongest hypothesis is renderer-main-thread starvation caused by a combination of:

  1. Unbounded serialization of complete referenced-chat histories
  2. Rehydration and normalization of the resulting large user-context record
  3. Concurrent streaming deltas from background tasks
  4. Dynamic @ result-section reconciliation
  5. Repeated layout measurement through ResizeObserver
  6. High-volume diagnostic logging and SQLite writes

Without a live renderer stack sample, it is not possible to determine whether the hottest operation is JSON processing, React reconciliation, Markdown or mention parsing, or layout callbacks.

Suggested fixes

  • Add an explicit character, token, byte, or item budget for referenced chats.
  • Avoid serializing a complete chat history into one unbounded JSON string.
  • Summarize or compact large referenced chats before adding them to a new task.
  • Process or normalize reference context outside the renderer thread.
  • Ensure hidden model context is removed before Markdown or mention parsing.
  • Add backpressure or stronger coalescing for renderer streaming events.
  • Virtualize and cap @ menu result sections.
  • Avoid observing the document root when only menu placement needs updating.
  • Reconcile interrupted and completed turns so they cannot remain marked as streaming.
  • Bound or rotate diagnostic SQLite storage and reduce trace-event write volume.
  • Add performance telemetry for reference size, renderer task duration, event-queue depth, and menu layout cycles.

Workarounds

  • Produce a concise handoff document from the source chat and reference that file instead of the complete chat.
  • Type an explicit relative file path instead of using the @ picker.
  • Avoid reopening a task containing very large chat references.
  • Reduce the number of simultaneous streaming tasks.
  • Force-quit and reopen the app after confirming background turns have completed.

Related issue

#32342 reports a closely related poisoned-task failure on Windows involving a server-backed ChatGPT conversation and a long prompt. This report is separate because the reproduction is on macOS, uses two large local Codex-chat references, and occurs with a short 312-character request. The renderer/backend split and unbounded reference-payload measurements are also independently captured here.

Privacy

Raw transcripts, desktop logs, local paths, identifiers, and attachments are intentionally not included because they may contain confidential workspace information.

This report contains aggregate measurements and generic application diagnostics only. It contains no project names, repository names, prompts, chat titles, source paths, thread or conversation identifiers, ticket identifiers, account identifiers, or tool output. Additional sanitized measurements can be provided if maintainers specify the fields needed.

View original on GitHub ↗

1 Comment

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #34454

Powered by Codex Action