Long CLI threads exceed Responses WebSocket message limit before auto-compaction (close code 1009)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What version of Codex CLI is running?
codex-cli 0.147.0
What subscription do you have?
ChatGPT subscription (exact tier unavailable in the CLI diagnostics)
Which model were you using?
Codex model with a reported 258,400-token context window
What platform is your computer?
Linux 7.0.0-28-generic x86_64 x86_64
What terminal emulator and version are you using (if applicable)?
Linux terminal, no multiplexer relevant to the reproduction
Codex doctor report
Not included because the issue is isolated to one large thread and the WebSocket peer supplied a definitive close code.
What issue are you seeing?
A long CLI thread consistently fails over from the Responses WebSocket transport to HTTPS, while fresh/small threads on the same client and network use WebSockets normally.
The stock CLI reports:
Falling back from WebSockets to HTTPS transport. stream disconnected before completion: websocket closed by server before response.completed
The current model-visible context reported by the client was approximately 225,029 tokens out of 258,400. The observed auto-compaction threshold was 244,800 tokens, so auto-compaction had not yet run.
To identify the otherwise-discarded close-frame details, I built the exact rust-v0.147.0 source and made a diagnostic-only change in responses_websocket.rs to include the received Message::Close(frame) code and reason in the existing error. The same request then reported:
websocket closed by server before response.completed (with code 1009 and reason Utf8Bytes(b""))
RFC 6455 defines close code 1009 as "Message Too Big." This strongly indicates that the serialized request/history exceeds the WebSocket peer's per-message limit before reaching Codex's auto-compaction threshold.
The client retries the apparently unchanged oversized request five times. Every WebSocket attempt closes, after which HTTPS fallback succeeds and the turn completes. This makes long threads slow but still usable.
Fresh threads do not reproduce the issue. A JSON parsing error would normally produce close code 1007 or a protocol/application error rather than 1009.
What steps can reproduce the bug?
- Use or resume a sufficiently long Codex CLI thread. In this reproduction, current model-visible context was about 225k tokens.
- Send a small text-only prompt such as
test again. - Observe five WebSocket reconnect attempts followed by fallback to HTTPS.
- Instrument the existing
Message::Close(frame)branch to retain the close-frame metadata. - Observe peer close code 1009 with an empty reason.
- Send the same prompt in a fresh thread and observe that WebSocket transport works normally.
The raw rollout and terminal captures are intentionally not attached because they contain private project and authentication-related data. The affected rollout was about 5.38 GB cumulatively on disk, but this report does not assume the full rollout is sent; the relevant observation is the 225k model-visible context plus the peer's close code.
What is the expected behavior?
- Measure or budget the serialized WebSocket request before sending it.
- If it exceeds the supported message size, compact first or switch directly to HTTPS.
- Do not retry an unchanged request after receiving close code 1009.
- Preserve and display WebSocket close-frame code/reason in normal diagnostics.
- Keep the WebSocket size threshold and auto-compaction threshold mutually compatible.
Additional information
Possibly related: #32512 documents a 16 MiB WebSocket per-message ceiling in the separate Desktop SSH-handoff path. This report concerns the ordinary CLI Responses sampling path, not artifact transfer.
No installed Codex files were modified. The diagnostic build came from the exact rust-v0.147.0 tag, and only the temporary error formatting was changed so the already-received close frame would be visible.
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 in responses_websocket.rs, especially the Message::Close(frame) handling, and reproduce with a sufficiently long CLI thread to observe close code 1009 and the repeated retries. Trace the request-size and auto-compaction paths; done means oversized requests are compacted or sent over HTTPS, unchanged 1009 requests are not retried, and close metadata is retained in diagnostics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100