[macOS] Opening local threads waits 5s for thread-owner-discovery timeout

Resolved 💬 7 comments Opened Aug 7, 2026 by yeliex Closed Aug 8, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using?

ChatGPT/Codex Desktop 26.803.41515 (build 6321)

Bundled app-server: 0.147.0-alpha.6.5

What platform is your computer?

  • macOS 27.0 (26A5388g)
  • Apple Silicon / arm64

What issue are you seeing?

After updating the desktop app, opening an existing local thread consistently takes about five seconds longer than before.

The delay is not in session parsing, thread/read, MCP startup, or a remote-environment handshake. It occurs before thread/read, while Desktop synchronously performs owner discovery for followExistingOwner.

The observed path in the packaged app is:

maybe_resume_started
  -> clientCoordination.findThreadOwner()
  -> local IPC request: thread-owner-discovery
  -> 5000 ms timeout
  -> maybe_resume_owner_discovery_failed (Error: timeout)
  -> thread/read

Desktop catches the timeout and continues, so the thread eventually loads, but every cold resume pays the full timeout.

Reproduction

  1. Start Codex Desktop.
  2. Open an existing local thread that is not already hydrated in the current renderer.
  3. Observe an approximately five-second loading delay.
  4. Repeat with other local threads.

In 12 sampled cold resumes, owner discovery failed after approximately 5001-5066 ms. Once the timeout fired:

  • thread/read started about 5-17 ms later.
  • thread/read itself completed in approximately 3-7 ms.

Representative sanitized log sequence:

07:18:43.775 maybe_resume_started
                 hostId=local
                 previousResumeState=needs_resume
                 previousStreamRole=null

07:18:48.777 maybe_resume_owner_discovery_failed
                 hostId=local
                 errorName=Error
                 errorMessage=timeout

The duration is 5002 ms.

Source-level correlation

Inspection of the packaged Desktop JavaScript shows that thread hydration is invoked with followExistingOwner: true.

Before starting hydration / thread/read, Desktop awaits:

clientCoordination.findThreadOwner({ hostId, conversationId })

For a local host, this sends a thread-owner-discovery IPC request with a 5000 ms timeout. The timeout appears to be a watchdog, not an intentional sleep: owner discovery should normally return quickly when all local clients answer.

The IPC router asks the other connected Desktop clients whether they can handle the request. If there is no current owner, all clients need to answer negatively. At least one connected client appears not to answer, so discovery waits until the watchdog expires.

Isolation performed

  • The affected host is hostId=local.
  • The request uses Desktop's local Unix-domain IPC socket under ~/.codex/ipc/; it is not an Internet/proxy/TUN request.
  • No MCP server startup occurs inside the five-second interval.
  • Plugin listing may run concurrently, but it completes before the owner-discovery timeout.
  • Session reading is fast after the timeout.
  • Removing the Popout Window hotkey did not change the behavior.
  • In a fresh-launch sample, the timeout occurred before hotkeyWindowHome and hotkeyWindowThread were created, ruling those windows out as the direct trigger.
  • Fully restarting Desktop with a newly created IPC socket still reproduces the problem.

The fresh-launch window timeline was:

07:18:40.800 primary routes mounted
07:18:41.740 hidden avatarOverlay main frame loaded
07:18:43.767 hidden avatarOverlay routes mounted
07:18:43.775 maybe_resume_started
07:18:48.777 owner discovery timeout
07:18:52.921 hotkeyWindowHome loaded
07:18:53.204 hotkeyWindowThread loaded

The persisted pet visibility state was already false, but Desktop still prewarmed a hidden avatarOverlay renderer. This makes that renderer a plausible non-responsive discovery client, but the current logs do not include enough client identity information to prove which IPC client failed to answer.

The same Desktop session also records IPC lifecycle warnings such as write EPIPE, ipc-connection-reset, and broadcasts received without registered handlers. These may be related to a stale or partially initialized renderer client.

Expected behavior

Opening a local thread should not block for the full owner-discovery watchdog.

If no other live window owns the thread, owner discovery should resolve immediately and hydration should proceed.

Suggested fix areas

  • Exclude non-thread surfaces such as avatarOverlay, browser surfaces, or other hidden/prewarmed renderers from thread-owner discovery.
  • Ensure every registered IPC client answers discovery with canHandle: false when it cannot own a thread.
  • Remove stale clients promptly when a renderer/window is destroyed or reset.
  • Fail owner discovery fast when a client has no relevant handler.
  • Avoid serially blocking thread/read on the full five-second watchdog.
  • Include client ID and window appearance in owner-discovery timeout diagnostics so the non-responsive client can be identified.

I can provide a narrowly sanitized log window or additional timing samples if useful. Raw logs and thread IDs are omitted for privacy.

Registered via Codex Papercuts skill

View original on GitHub ↗

7 Comments

github-actions[bot] contributor · 21 days ago

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

  • #37398

Powered by Codex Action

zhyuzhyu · 21 days ago

Additional timeline and A/B isolation:

  • This machine did not show the regression on 2026-08-06. The delay began on 2026-08-07, after ChatGPT/Codex Desktop 26.803.41515 (build 6321) and the Computer Use helper were installed/updated at approximately 09:44 local time.
  • Log counts reinforce that boundary: on 2026-08-06 there were 38 maybe_resume_started events and 0 owner-discovery timeouts; on 2026-08-07 there were 56 starts and 33 maybe_resume_owner_discovery_failed timeouts.
  • The legacy [mcp_servers.computer-use] entry is not the trigger. It has been enabled = false since at least 2026-07-17 and remained disabled in configuration backups from 2026-08-03 through 2026-08-05. No change to that legacy entry occurred immediately before this regression.
  • The current Computer Use path is the bundled computer-use@openai-bundled plugin through node_repl / @oai/sky, which launches SkyComputerUseService. The installed helper reports version 26.804.1000633 and was written on 2026-08-07 at approximately 09:44 local time.

The helper provides a reproducible A/B:

  1. With SkyComputerUseService running and connected to the Desktop IPC socket, an owner-discovery probe for an arbitrary nonexistent conversation fails to receive a response and the Desktop resume path reaches its 5-second watchdog.
  2. After terminating only SkyComputerUseService, the same probe returns no-client-found in approximately 4 ms, and local thread switching returns to its normal latency.
  3. Invoking the bundled Computer Use feature automatically relaunches the helper. Computer Use itself works, but the owner-discovery timeout immediately returns.

This suggests that the newly installed helper registers as a local IPC client but does not answer client-discovery-request / thread owner discovery with canHandle: false. That would explain why Desktop waits for the full watchdog even though no window owns the thread.

I am temporarily testing a rollback to the previous desktop/helper build because the prior build worked with the same MCP and provider configuration. The helper A/B is diagnostic only; permanently disabling it is not an acceptable workaround because it removes Computer Use.

maodeyu180 · 20 days ago

I submitted an in-app feedback report with logs and the affected session attached.

Feedback ID: 019fdbf9-dbfe-7c30-a6f3-2f37bbccaff6

Environment:

  • ChatGPT/Codex Desktop 26.803.41515 (build 6321)
  • Bundled Codex 0.147.0-alpha.6.5
  • macOS arm64
  • SkyComputerUseService 26.804.1000633 was running as a child of ChatGPT

After a full app restart, the same fixed ~5 second maybe_resume_owner_discovery_failed timeout reproduced on both an older thread and the current thread. After the timeout, thread/read completed in 4–6 ms and thread/resume in 31–96 ms.

WangBigHammer · 20 days ago

Confirming the same regression on macOS.

Environment:

  • ChatGPT/Codex Desktop 26.803.41515 (framework 151.0.7922.76)
  • Bundled Codex 0.147.0-alpha.6.5
  • macOS 26.6.1 (25G76), Apple Silicon arm64
  • SkyComputerUseService 26.804.1000633 installed 2026-08-07, currently running as a child of ChatGPT

Timeline: ChatGPT.app auto-updated at ~00:37 local on 2026-08-08 (previous Desktop build was 26.730.61639). Immediately after the update, every cold open of an existing local thread shows the full-screen OpenAI-logo loading spinner for several seconds. On 26.730.61639 the same threads opened instantly.

Additional data point supporting the owner-discovery-timeout theory (and ruling out rollout file size): as an experiment I stripped ~210 MB of inline base64 image payloads from 25 large rollout files (e.g. 20-27 MB files down to 1-2 MB), and cold opens still showed the same multi-second spinner afterwards — even for threads whose rollout is only ~100 KB. So the delay is independent of rollout size, consistent with a fixed ~5 s watchdog in the resume path rather than parsing/hydration cost.

leadingproblemsolver · 20 days ago

The helper A/B makes this look less like a timeout-tuning problem and more like an eligibility/lease-membership problem: a process being connected to IPC should not automatically make it a participant in thread-owner discovery.

I would give each client an explicit capability/lease registration, e.g.:

client_id
surface_kind = primary | popout | avatar_overlay | computer_use_service | ...
can_own_threads = true/false
owner_protocol_version
last_heartbeat

Then findThreadOwner() broadcasts only to live can_own_threads=true clients. A helper that never renders or controls thread state is excluded by construction rather than being required to answer canHandle:false forever.

For eligible clients, discovery should still be fail-fast and generation-bound:

snapshot eligible client set at discovery epoch E
wait only for that set
client disconnect => remove from E immediately
new client after E => not part of this request

That prevents a stale/half-initialized renderer from holding every thread open behind the global watchdog.

The diagnostic fields suggested in the issue would become much more actionable if timeout logs included the unresolved eligible client ids + surface kinds and their last heartbeat/handler registration state.

Regression cases:

computer-use helper connected, non-owner-capable => discovery resolves immediately
eligible primary + nonresponsive helper          => helper ignored
eligible owner disconnects during discovery      => removed, no 5s wait
stale eligible client heartbeat expired          => not queried
no eligible owner                                => no-client-found in milliseconds

The invariant is: ownership discovery waits on declared potential owners, not every process that happens to share the IPC bus.

ipv4sq · 19 days ago

experiencing the same issue here

tasu64 · 17 days ago

Additional A/B isolation from the same symptom, using a separately copied test bundle (the installed official app at /Applications/ChatGPT.app was not modified):

Baseline

  • Official Desktop 26.803.41515 (build 6321)
  • Repeated cold local-thread opens:
  • maybe_resume_started
  • approximately 5.0 s later: maybe_resume_owner_discovery_failed errorMessage=timeout
  • then thread/read completed in about 4–12 ms
  • thread/resume completed in about 40–120 ms
  • The hidden renderer was present with rendererWindowAppearance=avatarOverlay, rendererWindowVisible=false.
  • It received conversation broadcasts and sometimes logged Conversation state not found, even with the pet tucked and Computer Use PIP hidden.
  • Destroying that renderer was not a durable workaround because Desktop immediately prewarmed/recreated it.

Controlled test

In an isolated test copy based on official Desktop 26.803.81509 (build 6415), I disabled:

  1. followExistingOwner for normal local-thread navigation; and
  2. hidden avatarOverlay prewarming / related secondary-window surfaces.

Result across cold local-thread switches:

  • approximately 24–54 ms until content was available;
  • no maybe_resume_owner_discovery_failed timeout;
  • no avatarOverlay renderer startup/log traffic.

This is only an isolation result, not a proposed user patch or distribution. It strongly supports that the fixed delay is in the synchronous owner-discovery/secondary-renderer path rather than transcript I/O.

Suggested product fix

  • Start thread/read immediately and reconcile ownership asynchronously, or fail owner discovery fast when no eligible thread-owning window answers.
  • Exclude hidden/non-thread surfaces such as avatarOverlay and Computer Use PIP from thread-owner discovery and thread broadcasts.
  • Do not prewarm those renderers when the corresponding feature is disabled/tucked.
  • Restrict followExistingOwner to cases where a real primary/popout thread window is known to exist.
  • Add client/window identity to timeout diagnostics so the non-responsive IPC participant is visible.

No raw logs, thread IDs, titles, prompts, local project paths, or account data are included here. Related exact trigger report: #37686.