[macOS 26.803] SSH-connected host cannot resume some threads locally; orphan app-server blocks Remote pairing with 409
What version of the ChatGPT/Codex desktop app are you using?
Both Macs:
- ChatGPT desktop:
26.803.61601 - Build:
6396 - Bundled Codex CLI/app-server:
0.147.0-alpha.6.5
What platform are you using?
Both machines:
- macOS
27.0(26A5406e) - Apple Silicon (
arm64)
Topology:
- Controller Mac: uses ChatGPT Desktop > Settings > Connections > SSH to connect to the other Mac.
- Target Mac: also runs ChatGPT Desktop locally and should be directly available through QR-based Remote Control.
- Both apps are signed in to the same ChatGPT account/workspace.
- A legacy ChatGPT Classic app is installed on the target, but it and its background helper were not running while this reproduced.
What issue are you seeing?
A Mac that has been used as a ChatGPT Desktop built-in SSH target can be left with an SSH-started codex app-server that conflicts with the target Mac's local ChatGPT Desktop app.
The failure has two related user-visible symptoms:
- Thread access becomes frontend-dependent.
- Threads previously opened locally on the target can be resumed through built-in SSH after the target desktop app exits.
- Some threads opened or resumed through built-in SSH cannot later be opened/resumed from the target's local desktop app while the SSH-created app-server remains.
- This feels like the SSH runtime retains ownership or path/runtime context after the controller UI disconnects.
- Direct Remote Control setup on the target is blocked.
- The target first showed:
Unable to enable Remote Control. Make sure only one ChatGPT instance is running.- A later attempt showed:
Unable to get pairing code: Remote control failed to connect.- Target-side logs repeatedly reported:
WARN codex_app_server_transport::transport::remote_control::websocket
failed to connect to app-server remote control websocket:
HTTP error: 409 Conflict
body: {"detail":"Remote app server already online"}
reconnect_attempt=<n>
During the failure, the target had both a desktop-owned app-server and a separate background Unix-socket app-server:
/Applications/ChatGPT.app/.../codex app-server --listen stdio://
~/.local/bin/codex app-server --listen unix://
The Unix-socket process had PPID 1. A sanitized codex doctor --json summary for it reported:
background server is running
mode: ephemeral
pid file: missing
settings: missing
control socket: ~/.codex/app-server-control/app-server-control.sock
The local state and log databases passed integrity checks. This does not look like transcript/database corruption.
Observed sequence
This is the observed sequence; I have not yet reduced it to a fully deterministic single-command reproducer.
- On the target Mac, open and use several project threads in the local ChatGPT desktop app.
- Quit the target's local ChatGPT desktop app.
- From the controller Mac, add/enable the target under Settings > Connections > SSH.
- Open/resume project threads on the target through the built-in SSH connection.
- Disconnect SSH and quit ChatGPT Desktop on the controller.
- Relaunch ChatGPT Desktop locally on the target.
- Attempt to open/resume threads that were used over SSH and enable Control this Mac / obtain a QR pairing code.
- Some SSH-used threads fail to open locally, and Remote Control setup/reconnect logs repeated
409 Remote app server already online. - Inspecting the target shows an SSH/background
app-server --listen unix://alongside the local desktop app-server.
Recovery that worked temporarily
- Fully quit ChatGPT Desktop on the controller Mac, not only close its window.
- Disconnect the built-in SSH connection.
- Terminate the exact SSH-owned proxy/app-server on the target.
- Restart ChatGPT Desktop on the target.
After this cleanup, the target desktop could take ownership again and QR Remote setup could connect. The conflict can recur when an SSH/background app-server reappears.
Expected behavior
- Disconnecting or quitting a ChatGPT Desktop built-in SSH connection should cleanly stop its SSH proxy and ephemeral remote app-server, unless a managed daemon is intentionally configured.
- If a remote app-server already exists, the target's local desktop app should safely attach/take over or show which connection owns it and offer a supported disconnect action.
- A thread should remain openable from the target's local desktop app after it was opened through built-in SSH.
- QR Remote pairing should not be blocked indefinitely by a ghost/stale app-server connection.
codex doctorshould identify the owning frontend/session for a live Unix-socket app-server instead of reporting an ephemeral server with no PID/settings metadata.
Related issues
- #24542 — Desktop SSH proxy can keep an unmanaged app-server alive/respawn it.
- #31983 — idle SSH remote threads fail after restarting the connection.
- #28862 — stale Remote Control enrollment/app-server returns 409 and lacks a supported takeover path.
- #32321 — an orphaned desktop app-server can keep the Remote Control WebSocket and cause 409.
The distinct part here is the same macOS target also running ChatGPT Desktop locally: SSH-created runtime ownership makes thread access asymmetric and blocks direct QR Remote pairing on the current 26.803 build.
3 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional controlled comparison after testing a third Mac as the SSH target:
26.803.61601(build6396).27.0(26A5406e) on arm64.0.147.0-alpha.6.5.0.144.1.The working target also has both:
at the same time, and can move between local desktop and built-in SSH without the reported thread-access failure. Therefore, local Desktop + incoming SSH app-server coexistence is not inherently invalid.
The strongest differentiator observed so far is the SSH target runtime:
On the affected target,
codex doctor --jsonreports the Unix-socket background server asmode: ephemeralwith missing PID/settings files, while Remote Control logs continue to return repeated409 Remote app server already online.This narrows the suspected regression/incompatibility window to the target-side CLI/app-server update between
0.144.1and0.147.0-alpha.6.5, or to stale enrollment/identity state retained during that upgrade.A macOS “Allow in Background” setting is enabled on one affected target, but the system UI currently says the app is not running in the background. More importantly, that toggle would not own or terminate an SSH-started
~/.local/bin/codex app-server --listen unix://. It should not be treated as the root cause without a separate controlled test.No versions were changed during this comparison; the working
0.144.1target is being kept as a negative control.Additional regression detail from my reproduction:
This behavior only started after the latest Codex update. Before that update, I did not see the SSH-side Codex process remain behind after closing Desktop / IDE / CLI and disconnecting SSH.
The timing also appears correlated with the newer single-active-client / single-owner session validation behavior, where the same thread/session is prevented from being actively opened by more than one Codex frontend at a time.
I cannot confirm that this ownership validation is the root cause, but the observed failure is consistent with a stale owner not being released when an SSH-created Codex process survives its controlling client:
The important control remains local-only use:
So this looks like a regression introduced by the recent session single-owner enforcement interacting with SSH process cleanup/lifecycle rather than a general problem with the session data itself.
In other words, the uniqueness check is useful, but if an SSH-spawned process becomes stale, that protection can turn the leaked process into a persistent session lock affecting both remote SSH access and direct local access on the target machine.