Repository navigation
Codex Desktop SSH handoff fails for conversations larger than 16 MiB because rollout is sent as one WebSocket message #32512
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.707.41301
What subscription do you have?
Pro
What platform is your computer?
Linux 6.8.0-134-generic x86_64 x86_64
What issue are you seeing?
Summary
A cross-host handoff from Codex Desktop on macOS to a connected Ubuntu SSH
host consistently fails during transfer-host-artifacts when the task has a
large conversation history.
The rollout file is approximately 24.7 MB. Codex attempts to transfer it as one
WebSocket message whose serialized size is 32,936,861 bytes. The remote
app-server rejects it because its per-message limit is 16,777,216 bytes.
This prevents preserving and handing off long-running conversations.
Environment
- Codex Desktop client build: 26.707.41301
- Local codex-cli: 0.144.0-alpha.4
- Local OS: macOS
- Remote codex-cli: 0.144.1
- Remote platform: Ubuntu x86_64
- Connection type: Codex Desktop SSH host
- Source project: local Git checkout
- Destination: matching saved project on the SSH host
Steps to reproduce
- Create or use a Codex task with a sufficiently large conversation history.
- Ensure its rollout JSONL is larger than 16 MiB.
- Configure a matching Git project on a connected SSH host.
- In a separate coordinator task, hand off the large task to that SSH host.
- Wait for the cross-host handoff.
Expected result
The conversation and associated Git state are transferred to the SSH host, and
the task switches to the remote project.
Actual result
prepare-host-transfer completes, but transfer-host-artifacts fails:
Failed to continue on another host:
App-server connection closed before process exited
The remote app-server log contains:
websocket receive error:
Space limit exceeded: Message too long: 32936861 > 16777216
The SSH proxy subsequently reports:
Error: failed to relay data between stdio and socket
Caused by:
failed to copy data from stdin to socket
Broken pipe (os error 32)
Relevant sizes
- Source rollout JSONL: 24,702,507 bytes
- Source rollout lines: 18,217
- Serialized WebSocket message: 32,936,861 bytes
- Remote WebSocket limit: 16,777,216 bytes
Reproducibility
Consistent across repeated attempts.
The following did not help:
- Rebooting the SSH host
- Disabling and re-enabling the SSH connector
- Restarting the remote app-server
- Staging the task in a local Codex worktree before remote handoff
- Confirming both repositories are clean and at the same commit
Probable cause
The handoff creates a destination rollout.jsonl using a subprocess similar to:
cat > <handoff-directory>/rollout.jsonl
It appears to send the complete rollout to the remote subprocess in one
WebSocket/process-input message. Conversations whose serialized transfer
payload exceeds the app-server's 16 MiB per-message limit therefore cannot be
handed off.
Requested fix
Please stream or chunk handoff artifacts into messages substantially below the
WebSocket limit, rather than sending the complete rollout in one message.
For example:
- Send process input in 4–8 MiB chunks, or
- Transfer the file using a streaming filesystem operation or SSH file transfer.
It would also help if the UI surfaced the underlying size-limit error instead of
only reporting that the app-server connection closed.
Impact
There is currently no supported workaround that both:
- Completes the SSH handoff, and
- Preserves the complete conversation history.
Summarizing or truncating the task would lose the conversation state that the
handoff feature is intended to preserve.
What steps can reproduce the bug?
Steps to reproduce
- Create or use a Codex task with a sufficiently large conversation history.
- Ensure its rollout JSONL is larger than 16 MiB.
- Configure a matching Git project on a connected SSH host.
- In a separate coordinator task, hand off the large task to that SSH host.
- Wait for the cross-host handoff.
What is the expected behavior?
Please stream or chunk handoff artifacts into messages substantially below the
WebSocket limit, rather than sending the complete rollout in one message.
Additional information
No response
Activity
sam-ulrich1 commentedon Jul 24, 2026
Please fix
bbingz commentedon Jul 26, 2026
Analysis (community)
Residual analysis for #32512 (Desktop SSH handoff fails for conversations larger than ~16 MiB because the rollout is sent as one WebSocket message) under docs/contributing.md — invitation-only. No unsolicited PR.
Root-cause hypothesis
This is a process/writeStdin artifact transfer failure, not primarily a large
thread/resumeresponse. Desktop sent the whole rollout as one base64delta(~24.7 MB → ~32.9 MB wire); the remote app-server Unix WebSocket acceptor still uses default ~16 MiB Tungstenite limits and fatal-closes on receive overflow — even though the protocol already supports chunkedprocess/writeStdindeltas.Verified at HEAD
4c43465133:1. Protocol already has the right shape.
codex-rs/app-server-protocol/src/protocol/v2/process.rs—process/writeStdincarries optionaldelta_base64+close_stdin.process_exec_processor.rsdecodes one supplied delta and writes it to the process. Multiple smaller deltas are valid; a single huge delta is what blows the frame.2. Issue body pins the exact path.
#32512 reports a ~24,702,507-byte rollout becoming one ~32,936,861-byte WebSocket message, rejected at 16,777,216 bytes on the remote app-server during
transfer-host-artifacts— classic ~4/3 base64 expansion of a single delta.3. Unix acceptor keeps default limits.
codex-rs/app-server-transport/src/transport/unix_socket.rsupgrades withaccept_asyncunder default Tungstenite frame/message limits. A receive-limit error breaks the inbound loop (transport/websocket.rs); the connection then emitsConnectionClosed. By contrast, an in-tree remote client config raises frame/message limits to 128 MiB (app-server-clientremote config) — that raise is not applied to the Unix-socket server acceptor.4. Scope honesty (MIXED).
thread/resumewas overbroad for this issue; Codex Desktop SSH handoff fails for conversations larger than 16 MiB because rollout is sent as one WebSocket message #32512’s bytes are stdin artifact transfer.Ranked fix outline:
process/writeStdinas multipledelta_base64chunks under the wire cap; final chunk +close_stdin.Fail-first tests on the OSS side can mock multi-delta vs single-delta without needing full Desktop. Happy to help with acceptor config + error string. No unsolicited PR.