Codex CLI stream repeatedly reconnects then falls back after websocket closes before response.completed

Open 💬 1 comment Opened Jul 2, 2026 by uditgoenka

Summary

Codex CLI can enter a repeated reconnect loop during a model turn when the WebSocket stream closes before response.completed. The UI retries up to 5/5, then falls back from WebSockets to HTTPS transport, but the user is left waiting in a degraded/stalled state instead of seeing a clean recovery, retry boundary, or actionable error.

This report is intentionally sanitized. The screenshots only show the generic transport error text and no private prompt/output data, so I am transcribing the visible messages rather than attaching session contents.

Environment

  • Codex CLI: codex-cli 0.142.5
  • Platform: macOS arm64
  • Model/profile visible in TUI: gpt-5.5 xhigh
  • Invocation shape: interactive Codex CLI session resumed from local history
  • Network/account details and private thread contents are intentionally omitted

Visible UI messages

The TUI showed repeated reconnect attempts:

Reconnecting... 3/5 (42s • esc to interrupt)
└ Stream disconnected before completion: websocket closed by server before response.completed

Then later:

Reconnecting... 5/5 (1m 04s • esc to interrupt)
└ Stream disconnected before completion: websocket closed by server before response.completed

After exhausting WebSocket reconnect attempts, the TUI showed:

⚠ Falling back from WebSockets to HTTPS transport. stream disconnected before completion: websocket closed by server before response.completed

Impact

  • The active turn appears unreliable/stalled for over a minute.
  • The user has to decide whether to interrupt, wait, or retry, without a clear state like “request recovered over HTTPS,” “request will be retried safely,” or “turn failed and no work is continuing.”
  • In long-running or critical resumed sessions, this is risky because interrupting may alter goal/turn state while waiting can burn time and possibly usage.

Reproduction shape

I do not have a minimal synthetic repro, but the observed shape is:

  1. Resume an existing Codex CLI session.
  2. Start or continue a model turn using gpt-5.5 xhigh.
  3. During streaming, the WebSocket closes before response.completed.
  4. Codex shows reconnect attempts 3/5 through 5/5 over about one minute.
  5. Codex falls back from WebSockets to HTTPS transport with the same websocket closed by server before response.completed message.

Expected behavior

  • WebSocket-to-HTTPS fallback should be seamless if the request can continue safely.
  • If continuation is not safe, the UI should mark the turn failed with an explicit terminal state and preserve the accepted user message.
  • The UI should expose enough diagnostic detail to distinguish:
  • transient transport reconnecting;
  • successful fallback and continued stream;
  • unrecoverable stream failure;
  • detached/unknown backend turn still running.
  • Interrupting during reconnect/fallback should not leave ambiguous goal/session state.

Actual behavior

  • The UI shows repeated reconnect attempts and fallback text, but not a clear terminal or recovered state.
  • The user sees a long stalled/reconnecting period and must manually decide whether to interrupt.
  • The exact error text repeats: websocket closed by server before response.completed.

Suggested fixes

  1. Add a clear post-fallback state: recovered over HTTPS, retrying safely, failed terminally, or backend state unknown.
  2. Show a request/turn diagnostic id in the UI or logs for this failure path.
  3. Preserve accepted user prompts and active goal state cleanly across reconnect/fallback/interrupt boundaries.
  4. Add an HTTPS-only or disable-WebSockets option for users/networks that repeatedly hit this condition.
  5. Avoid making esc/interrupt the only practical recovery action when the backend turn state is uncertain.

Related issues

These look closely related, but I am filing this separately with current CLI/version details and the exact observed retry/fallback sequence:

  • #22156
  • #28115
  • #26696
  • #18960
  • #20739
  • #30777

Privacy note

No raw transcript, prompts, outputs, credentials, project names, or private paths are included here.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗