[Windows] CLI hangs indefinitely during shell tool execution with large output (Get-Content -Raw)
What version of Codex CLI is running?
codex-cli 0.122.0
What subscription do you have?
plus
Which model were you using?
5.4 (though issue occurs on any model)
What platform is your computer?
Windows
What terminal emulator and version are you using (if applicable)?
terminal
What issue are you seeing?
The Codex CLI intermittently hangs or stalls indefinitely in a "Working..." state when executing shell commands that produce large or rapid output (e.g., Get-Content -Raw in PowerShell). Interrupting the process with ESC often does not cleanly recover the session, and subsequent commands are likely to fail.
Commands that return immediately but produce empty output or a massive stream of text trigger this behavior.
What steps can reproduce the bug?
- Start Codex CLI on Windows (using PowerShell as the local shell).
- Create a large text file:
powershell -Command "1..50000 | % { 'Test string ' + $_ } | Out-File -Encoding utf8 large_file.txt"
- Ask the agent to read the file using the raw command:
Read large_file.txt using Get-Content -Raw
- Observation: The CLI hangs indefinitely in the "Working..." state. The PowerShell subprocess remains active but blocked.
What is the expected behavior?
The shell command should execute successfully, output should be captured (and truncated if it exceeds the maximum byte limit), and control should be returned to the agent loop without deadlocking.
Additional information
Root Cause Analysis
This is a concurrency deadlock caused by back-pressure on a bounded async event channel in the shell execution pipeline:
- When a command like Get-Content -Raw produces a massive burst of text, the read_output background task in codex-rs/core/src/exec.rs reads it in chunks.
- For each chunk, it emits a UI delta event via a bounded channel (stream.tx_event.send(event).await).
- If the UI or agent loop cannot consume these events fast enough, the channel fills up, and the send().await call blocks the read_output task.
- Because the Rust stream reader is suspended, the OS process pipe buffer (~64KB on Windows) fills up.
- The child process (PowerShell) blocks indefinitely trying to write to stdout.
- The main agent loop is stuck waiting on child.wait(), resulting in a permanent "Working..." state.
Proposed Fix (PR Incoming)
Replace the blocking .await call with a non-blocking .try_send() when emitting streaming UI events (ExecCommandOutputDeltaEvent).
1 // codex-rs/core/src/exec.rs (Inside read_output)
2 // Change:
3 // let _ = stream.tx_event.send(event).await;
4 // To:
5 let _ = stream.tx_event.try_send(event);
This allows the stream reader to intentionally drop intermediate UI updates when under back-pressure, keeping the pipe drained. The actual process output is still independently aggregated in memory without back-pressure and successfully returned at the end of the tool call.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗