/resume selecting the currently active session causes TUI to exit immediately
What version of Codex CLI is running?
codex-cli 0.118.0
What subscription do you have?
ChatGPT Plus
Which model were you using?
_No response_
What platform is your computer?
Darwin 25.2.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Terminal.app
What issue are you seeing?
Running /resume and selecting the currently active session in the picker causes the TUI to exit immediately. The user loses their current session without warning.This also occurs if you /resume the same session twice in a row without exiting.
What steps can reproduce the bug?
1.Start codex and begin a new interactive session
2.Send at least one message so the session is persisted
3.Type /resume and select the currently active session from the picker
4.The TUI exits immediately
This also occurs if you /resume the same session twice in a row without exiting.
What is the expected behavior?
Selecting the already-active session should be a no-op — the picker closes and the user returns to their current session unchanged.
Additional information
Root cause
SessionSelection::Resume in [app.rs:4055](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/app.rs#L4055) does not check whether the selected thread is already active. The sequence:
[resume_thread(same_id)](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/app.rs#L4096)— succeeds (idempotent for an already-subscribed connection)[shutdown_current_thread()](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/app.rs#L4101)— unconditionally calls[thread_unsubscribe(same_id)](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/app.rs#L1544)- App-server sees zero remaining subscribers (
has_subscriberscheck) → spawns[shutdown_and_wait](https://github.com/openai/codex/blob/8d19646/codex-rs/app-server/src/codex_message_processor.rs#L5428)→ broadcastsThreadClosed - TUI receives live
ThreadClosed([chatwidget.rs:6447](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/chatwidget.rs#L6447)) →[on_shutdown_complete()](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/chatwidget.rs#L3920)→ immediate exit
Even without the exit, [replace_chat_widget_with_app_server_thread](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/app.rs#L3319) would destroy and rebuild the ChatWidget, discarding any local UI state that AppServerStartedThread does not carry (the fields captured by [capture_thread_input_state](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/chatwidget.rs#L3116) — pending steers, queued messages, collaboration mode, etc.).
Existing test coverage
Two existing tests validate two legs of the chain independently:
[thread_unsubscribe_unloads_thread_and_emits_thread_closed_notification](https://github.com/openai/codex/blob/8d19646/codex-rs/app-server/tests/suite/v2/thread_unsubscribe.rs#L84)[live_app_server_thread_closed_requests_immediate_exit](https://github.com/openai/codex/blob/8d19646/codex-rs/tui/src/chatwidget/tests/app_server.rs#L576)
Other callers of shutdown_current_thread are safe: /clear always creates a new thread afterward, /fork always produces a new thread ID, and Ctrl+C sets pending_shutdown_exit_thread_id first.
Suggested fix
Add an early no-op guard before the cwd/config rebuild and resume_thread call, so the operation becomes a no-op when current == target, falling through to the shared schedule_frame() exit:
if self.chat_widget.thread_id().as_ref() != Some(&target_session.thread_id) {
// ... existing resume logic unchanged
}
Reference implementation with regression test: [exqqstar/codex@bae38ef](https://github.com/exqqstar/codex/commit/bae38ef)
Happy to submit a PR if this aligns with the team's intended approach.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗