Skip to content

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

Closed

Description

@yeliex

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

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    on Aug 7, 2026
  2. github-actions commented on Aug 7, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. zhyuzhyu commented on Aug 7, 2026

    @zhyuzhyu

    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.

  4. maodeyu180 commented on Aug 7, 2026

    @maodeyu180

    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.

  5. WangBigHammer commented on Aug 7, 2026

    @WangBigHammer

    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.

  6. leadingproblemsolver commented on Aug 7, 2026

    @leadingproblemsolver

    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.

  7. ipv4sq commented on Aug 9, 2026

    @ipv4sq

    experiencing the same issue here

  8. tasu64 commented on Aug 11, 2026

    @tasu64

    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.

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

Metadata

Metadata

Assignees

Labels

Papercuts 2026appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingperformance

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions