Repository navigation
Remote SSH disconnects when large plugin/list response blocks WebSocket pongs #41573
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.825.41651
What subscription do you have?
ChatGPT Pro Lite
What platform is your computer?
Client: Darwin 24.6.0 arm64 arm; server: Linux 6.8.0-111-generic x86_64 x86_64
What issue are you seeing?
Codex Desktop Remote SSH repeatedly disconnects with WebSocket code 1006, although SSH remains available and the persistent remote app-server stays alive.
A protocol probe identified this sequence:
plugin/listreturns approximately 7.57 MB containing over 3,300 remote plugin summaries.- The response is emitted as one unfragmented WebSocket frame.
- While that frame drains through the SSH proxy, pong frames cannot interleave.
- Desktop continues sending pings, but its 60-second no-pong watchdog eventually terminates the healthy proxy.
The app-server does not appear globally stalled:
Cached plugin/list: 0.31 s, 7,568,723 bytes, 1 frame
Forced plugin/list: 9.47 s, 7,573,180 bytes, 1 frame
Concurrent config/read: 2-6 ms
During an actual failure, server-side monitoring showed continuing proxy output, acknowledged TCP traffic, and an empty TCP send queue. The persistent app-server retained the same PID after the proxy was terminated.
A controlled slow-reader test reproduced the behavior without SSH: once the large frame began, subsequent pongs and small responses remained unavailable until the frame completed, causing a no-pong watchdog to fire.
What steps can reproduce the bug?
- Enable
pluginsandremote_pluginon a Linux Codex host. - Connect using Codex Desktop Remote SSH.
- Trigger or wait for a background
plugin/list. - Observe the request timeout, WebSocket close code
1006, and reconnection. - Confirm that SSH and the persistent app-server remain alive.
The failure also reproduced with SSH multiplexing disabled and a fresh authenticated SSH connection.
What is the expected behavior?
Large app-server responses should not block WebSocket control traffic or disconnect the remote host.
Additional information
As a size-control experiment, setting
[features]
remote_plugin = falsereduced the response from approximately 7.57 MB to 319 KB while retaining bundled and locally curated plugins.
Activity
TheNewMikeMusic commentedon Sep 5, 2026
Possible related Android Remote / hosted relay case with fresh payload measurements. This is not confirmation of the SSH-specific unfragmented-frame / no-pong failure described above.
Environment:
The phone can open tasks, but refreshing/reconnecting Remote remains sluggish after restarting the host app. Actual host logs contain initialization requests from
app_server.client_name="codex_chatgpt_android_remote"toplugin/listandmcpServerStatus/list.Read-only, isolated replays against the official bundled app-server produced:
plugin/listplugin/installedcontrolmcpServerStatus/listthread/listfor pinsThe full remote marketplace contained 3,710 plugin summaries, of which 33 were marked installed. The remote marketplace accounted for 8,337,629 bytes of compact UTF-8 JSON; its
interfacefields alone accounted for about 6.31 MB.Replay details:
codex app-server --listen stdio://was used, withCODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1to avoid registering an additional Remote host.capabilities.experimentalApi: true.plugin/listandplugin/installedusing the samecwds, with default marketplace options and without forcing a catalog refetch.Limits:
In addition to transport fragmentation / control-frame scheduling, could the mobile initialization path avoid fetching the full marketplace before ready state? If it only needs installed plugin mentions,
plugin/installedwas about 70 times smaller in this environment. Full catalog loading could remain on the explicit marketplace browsing path.No private task content, task/host/account IDs, credentials, catalog payload, or raw logs are included.
rellaqaq commentedon Sep 7, 2026
Additional independent Android/hosted-Remote measurements, plus a caveat about the
remote_plugin=falseworkaround. This does not confirm the SSH-specific no-pong failure for hosted Remote.Environment: official macOS Desktop 26.901.51231 / build 8109, bundled app-server 0.153.4. One Android phone uses a WireGuard tunnel over cellular data. The owner has now supplied the About screenshot: ChatGPT Android 1.2026.244 (21). Reported symptom is intermittent searching for the desktop or reconnecting, not initial pairing failure.
Two isolated replays of the official bundled stdio app-server, using
CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1,experimentalApi: true, identicalcwds, omitted marketplace options, and no forced refetch:plugin/listplugin/installedremote_plugin=false,plugin/listremote_plugin=false,plugin/installedDefault
plugin/listtook 2,327 / 2,269 ms cold and 837 / 499 ms warm;plugin/installedtook 13 / 12 ms. These are local individual RPC timings, not mobile end-to-end connection measurements. Different list/installed counts reflect the distinct responses, not an assumed common enumeration.Crucially, installed-only name comparison across the feature override found seven installed/enabled plugin names absent, with no replacement names. Thus, in this environment, disabling
remote_pluginis not merely suppressing marketplace discovery while retaining every installed plugin. We did not persist that override. No catalog payloads were retained, and all auxiliary processes exited without registering another Remote owner.An installed-only initialization path is about 185 times smaller here while retaining all 22 entries. Could the official Android ready-state path use
plugin/installedwhen it needs installed mentions and defer the full catalog until marketplace browsing? Alternatively, is there a supported installed-preserving configuration for this case?Limits: Android's exact RPC parameters, spinner critical path, relay ACK occupancy, and control-frame scheduling were not captured. Earlier separate host-side TLS EOF reconnects recovered automatically in 1–4 seconds. A later outage lasted about70seconds and included a30-second required-server-token refresh timeout followed by a logged35-second retry deferral. These are separate transport/retry observations, not proof that the catalog caused the disconnects. Current hosted relay source segments envelopes, so the original SSH unfragmented-frame explanation cannot simply be transferred. No confirmed production fix is claimed.
Owner update,2026-09-07: a fresh screenshot shows the Mac indicator green while a conversation remains on loading skeletons. The owner reports that manually disconnecting/reconnecting mobile Remote was necessary to restore loading. Host transport had reconnected before that screenshot, and Android thread/resume requests reached the host around the same period. This establishes the recurrent user-visible failure, but not whether an undelivered response, client recovery state or catalog initialization was responsible. No configuration change, plugin removal or pairing reset was performed.
Only aggregate diagnostics are included; no account/task/host identifiers, private endpoints, credentials, plugin payloads, or raw logs.
bradleygibsongit commentedon Sep 10, 2026
Independent macOS → Linux Remote SSH reproduction, tested September 9–10, 2026. Upgrading the remote CLI/app-server from 0.153.4 to 0.154.0 did not resolve the catalog timeout. Setting
features.remote_plugin = falseand restarting the remote app-server restored responsiveness in our tests and in actual desktop use.Environment:
Before the feature change:
plugin/listandthread/starttimeouts.plugin/listreturned 8,178,596 bytes, including 3,642 available remote plugin summaries (not installed-plugin count).account/read196 ms,model/list198 ms.After setting the following in the remote configuration and restarting the app-server:
plugin/listshrank to 118,865 bytes and completed over SSH in 3.602 s, then 2.061 s.account/readrequests stayed around 190 ms, including checks at 20, 40, and 60 seconds on the same connection.Measurement method: read-only JSON-RPC requests over the existing app-server's Unix socket or its supported
codex app-server proxySSH transport, initialized withexperimentalApi: true;plugin/listparameters were{}, without forced refetch. Byte counts are the received JSON-RPC message payload sizes.Limits: the network also showed constrained throughput/retransmissions during earlier testing. We did not directly capture WebSocket fragmentation or prove the no-pong watchdog mechanism here. This is a short-term workaround result, not proof of long-term stability. No plugins were uninstalled, but we have not verified that disabling
remote_pluginpreserves every installed plugin's availability.This adds a reproduction on 0.154.0 and a measured workaround result supporting investigation of full-catalog traffic on the interactive SSH connection.