TUI freezes during idle long wait while session continues and completes

Resolved 💬 5 comments Opened May 1, 2026 by 92645417d9e5c763259dbebc306e3e Closed May 17, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

0.128.0

What subscription do you have?

Plus

Which model were you using?

_No response_

What platform is your computer?

Linux

What terminal emulator and version are you using (if applicable)?

alacritty

What issue are you seeing?

The Codex TUI can freeze during a long wait when there is no token streaming or assistant chatter.
The backend session continues running and can complete, but the visible TUI stops updating.

In my case, I intentionally prompted agents to avoid filler/status chatter during long waits. With that setup, the TUI animation stopped, but the task still completed in the background.

I had a local completion hook that sends a notification when the task finishes. That notification arrived even though the TUI was frozen. The old TUI process was still alive until manually killed:

PID 27495
~/.codex/bin/codex-0.128.0
state: Sl+
tty: pts/10

After completion, the session log contained task_complete, and the completion record had notified: true.

What steps can reproduce the bug?

  1. Start or resume a Codex CLI TUI session.
  2. Run a task that waits for a long time on background work.
  3. Prompt the agents not to emit periodic filler/status text while waiting.
  4. Leave TUI animations enabled so a frozen UI is visible.
  5. Wait through an idle period with little or no token streaming.

Observed result: the TUI can freeze while the backend session continues and eventually completes.

What is the expected behavior?

The TUI should remain responsive during long idle waits, or recover/repaint once backend events arrive. If the backend task completes, the TUI should visibly reflect completion without needing a second Codex session or manual process cleanup.

Additional information

Codex CLI helped identify a likely area to inspect: the TUI appears to rely on activity from streamed rollout/items or similar backend updates to keep the interface moving during long waits.

This issue was written with the assistance of Codex CLI.

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 3 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #19331

Powered by Codex Action

etraut-openai contributor · 3 months ago

If you're able to repro this, please /feedback and post session ID.

92645417d9e5c763259dbebc306e3e · 3 months ago

109-tui-task-frame-heartbeat.patch
this codex-generated patch solves the issue I mentioned for me, which has not been encountered again in 0.128.0 or 0.129.0-alpha.3

handsomeZR-netizen · 3 months ago

I investigated the Windows PowerShell Working... hang on current main.

Environment

  • OS: Microsoft Windows NT 10.0.26200.0
  • Shell: PowerShell 7.6.1
  • Codex commit: 6d65686313 feat: make ToolExecutor an async trait (#22560)
  • Local branch: windows-pwsh-working-hang-fix
  • Codex CLI version: codex-cli 0.130.0
  • Rust toolchain in codex-rs: cargo 1.93.0, rustc 1.93.0

Summary

The original bounded-channel stdout-reader backpressure hypothesis no longer matches current main: core session events use an unbounded channel, app-server-client treats command output deltas as best-effort, and rollout storage does not persist ExecCommandOutputDelta.

The most plausible remaining Working... path is in the TUI active-thread routing queue. That queue made every active-thread notification effectively lossless by spawning a waiting send task when the per-thread channel was full. A large CommandExecutionOutputDelta backlog could therefore keep TurnCompleted behind many best-effort output events, leaving the UI in Working... until the backlog drained.

Findings

  • stdout/stderr reader path: legacy exec reads pipes in codex-rs/core/src/exec.rs; unified exec reads process output into a broadcast/output buffer in codex-rs/core/src/unified_exec/process.rs.
  • intermediate output delta path: legacy read_output emits ExecCommandOutputDelta; unified async_watcher.rs emits the same event after transcript append.
  • final output aggregation path: legacy final output is aggregated in exec result construction; unified final command end comes from the transcript and process exit status.
  • completion / exit status path: TurnCompleted clears TUI Working... through ChatWidget::handle_turn_completed_notification -> on_task_complete / finalize_turn.
  • queue classification: codex-rs/app-server-client/src/lib.rs already makes CommandExecutionOutputDelta best-effort and preserves TurnCompleted, ItemCompleted, and transcript deltas.
  • remaining gap: codex-rs/tui/src/app/thread_routing.rs did not preserve that lossless/best-effort split for the active thread queue.
  • manual PowerShell validation: a 50,000-line temp file under %TEMP%\codex-pwsh-hang-repro was read with Get-Content -Raw in about 36.5 ms; no direct PowerShell hang was observed.

Local patch

I applied a small local patch:

  • In codex-rs/tui/src/app/thread_routing.rs, active-thread queue overflow now drops known best-effort progress/output notifications instead of spawning waiting send tasks for them. This lets lossless events such as TurnCompleted bypass a command-output backlog.
  • In codex-rs/tui/src/app/tests.rs, I added a regression test that fills a capacity-1 active-thread queue with command output delta, queues another output delta, then queues TurnCompleted; the expected next lossless event is TurnCompleted, and Working... clears.
  • In codex-rs/app-server/src/in_process.rs, I aligned the lower-level in-process app-server must-deliver helper with app-server-client for TurnCompleted, ItemCompleted, assistant/plan/reasoning deltas, while keeping CommandExecutionOutputDelta best-effort.

Validation

Commands run:

cargo test -p codex-tui output_delta_backlog_does_not_delay_turn_completed_for_active_thread
cargo test -p codex-app-server guaranteed_delivery_helpers_cover_terminal_server_notifications
cargo fmt
cargo fmt --check

Results:

cargo test -p codex-tui output_delta_backlog_does_not_delay_turn_completed_for_active_thread:
1 passed.
cargo test -p codex-app-server guaranteed_delivery_helpers_cover_terminal_server_notifications:
1 passed.
cargo fmt completed.
cargo fmt --check completed.

Question

Would maintainers prefer a PR for the TUI active-thread queue best-effort drop fix first, or should a broader follow-up also make core ExecCommandOutputDelta emission explicitly best-effort even though the current core event channel is unbounded?

etraut-openai contributor · 3 months ago

I think this is addressed by https://github.com/openai/codex/pull/21870. If you see similar symptoms, please file a new bug report using /feedback.