[Windows][App][Chrome] Same conversation enters ~22 Hz active-writer retry loop across desktop and Chrome side panel
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
OpenAI.Codex 26.810.4967.0
Chrome integration runtime: 26.810.41047
Google Chrome: 150.0.7871.125
What subscription do you have?
ChatGPT Pro (5x, US$100/month tier)
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Pro, build 26200)
What issue are you seeing?
Opening the same Codex/ChatGPT conversation in the Windows desktop app and the ChatGPT Chrome extension side panel causes a rapid cross-client ownership/retry loop. The contention is bidirectional: it occurs whether the desktop app opens the conversation first or the Chrome side panel opens it first.
The first client does not need to be actively viewing the conversation, generating a response, or controlling a browser. Once that client has opened the conversation, its retained ownership/activity state can continue to trigger contention when the other client later opens the same conversation. In repeated tests, this stale competing state persisted until the first client/app was restarted, even when the conversation was no longer being actively browsed there.
Both surfaces become visually unstable. The desktop repeatedly shows and hides this message:
已在另一个应用中打开,请先在那边关闭会话,才能在这里继续
English meaning: “This conversation is open in another app. Close it there before continuing here.”
The warning does not settle into a stable blocked or read-only state. Restarting the client that previously opened the conversation clears its retained competing state, but users should not need to restart an application merely to release a conversation that is no longer active there.
A synchronized 15-second video/log capture confirms that this is a high-frequency state-machine loop rather than only a rendering artifact. During the exact video interval, the desktop emitted:
- 338
thread_stream_role_changedevents; - 338
maybe_resume_startedevents; - 338 browser-session route captures;
- 337 failed
thread/resumerequests with error code-32600; - 337 request failures reporting
thread [redacted] already has an active writer.
That is approximately 22.5 ownership/resume cycles per second for the full recording.
Representative redacted sequence:
response_routed ... errorCode=-32600 method=thread/resume
Request failed ... error={"code":-32600,"message":"thread [redacted] already has an active writer"}
maybe_resume_started ... previousResumeState=needs_resume previousStreamRole=null
Failed to resume conversation ... already has an active writer
thread_stream_role_changed ... previousRole=null role=owner
IAB_LIFECYCLE webview captured browser use session route
A 20.82-second process sample while the contention remained active showed:
- desktop
codex.exe app-server: 19.91 CPU-seconds, approximately one logical core; - desktop renderer: 20.83 CPU-seconds, approximately one logical core;
- Chrome extension
codex.exe app-server: 0.02 CPU-seconds; - Chrome
extension-host.exe: effectively 0 CPU-seconds.
This points to an active retry/IPC loop in the desktop client after the writer conflict, rather than CPU activity in the Chrome extension host.
What steps can reproduce the bug?
Desktop first
- Open an existing conversation in the Windows desktop app.
- Stop actively using that conversation. It does not need to be generating, controlling a browser, or even remain the currently viewed conversation. Do not restart the desktop app.
- Open the same conversation in the ChatGPT Chrome extension side panel.
- Observe both clients continuously flashing and the desktop ownership warning repeatedly appearing and disappearing.
Chrome first
- Open an existing conversation in the ChatGPT Chrome extension side panel.
- Stop actively using that conversation, but leave Chrome/the extension runtime running without restarting it.
- Open the same conversation in the Windows desktop app.
- Observe the same repeated contention in the opposite opening order.
The issue has been reproduced multiple times in both directions. The trigger is retained per-conversation client state, not simultaneous active browsing: opening the conversation previously and keeping that client runtime alive is sufficient.
Trigger matrix
| Condition | Result | Evidence scope |
|---|---|---|
| Desktop opened conversation first; Chrome opens it later | Reproduces | Repeated observation; one synchronized video/log capture |
| Chrome opened conversation first; desktop opens it later | Reproduces | Repeated observation |
| First client is not generating or controlling a browser | Reproduces | Repeated observation |
| Conversation was opened earlier but is not currently being viewed; client has not restarted | Reproduces | Repeated observation |
| Client retaining the competing state is restarted | Contention clears | Repeated observation |
What is the expected behavior?
Only one client should hold the active-writer role. When another client opens the same conversation, it should receive one rejection and remain in a stable non-owner/read-only or blocked state until an ownership-change event occurs.
The client should not immediately retry thread/resume, reassert role=owner, recapture the browser route, or repeatedly mount/unmount the warning UI.
When a client is no longer actively viewing or using a conversation, its writer/activity lease should be released without requiring the entire client to restart.
Additional information
The observable loop appears to be:
- Desktop attempts
thread/resume. - App-server rejects it because another active writer exists.
- Desktop immediately returns to
needs_resume. - Desktop reports itself as
role=ownerand recaptures the browser route. - Desktop retries approximately 22 times per second.
Suggested engineering checks:
- transition an
already has an active writerresponse into one stable observer/blocked state; - wait for an ownership-change event or use bounded backoff instead of immediate retries;
- make browser route capture/release idempotent when writer acquisition fails;
- verify that hiding, minimizing, navigating away from, or closing a conversation reliably updates its writer/activity lease;
- add a two-client integration test covering both opening orders and an idle/minimized first client.
Related issues found before filing:
- #37403 reports
already has an active writerduring Desktop ↔ Remote Control/CLI handoff on macOS. - #37856 reports stale ownership between VS Code clients.
This report is distinct because it covers the Windows desktop app ↔ ChatGPT Chrome side panel, is bidirectionally reproducible, and includes synchronized evidence of a sustained ~22.5 Hz retry/render loop.
Attachments:
- public-safe 1080p/30 FPS video, 15 seconds; Chrome conversation body blurred;
- redacted log events covering the exact video interval;
- capture summary with counts, process comparison, timestamps, and hashes.
Evidence scope: the attached synchronized video captures one concrete contention direction and proves the sustained retry/render loop for that run. The reverse opening order and the persistence after merely opening a conversation earlier were each reproduced repeatedly but are described as reproduction observations rather than being claimed as simultaneously shown by this single video.
Privacy: conversation IDs, request IDs, local paths, account information, and Chrome conversation content are redacted from public attachments. Full-resolution evidence is retained privately if maintainers need it through a private support channel.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the desktop app-server handling of thread/resume after an “already has an active writer” rejection, including thread_stream_role_changed and maybe_resume_started. Reproduce the two-client scenario in both opening orders and inspect the suggested two-client integration test. Done means one stable blocked or read-only state, no rapid retry or route recapture loop, and release of idle conversation ownership without restarting the client.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop, distributed-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100