TUI: resolve_elicitation routed to wrong thread_id on multi-session race condition
What version of Codex CLI is running?
0.130
What subscription do you have?
pro
Which model were you using?
_No response_
What platform is your computer?
_No response_
What terminal emulator and version are you using (if applicable)?
_No response_
What issue are you seeing?
Bug Description
When multiple Codex sessions (threads) are active in the TUI, a resolve_elicitation request can be routed to the wrong session, causing an elicitation request not found error and leaving the TUI in a hung state.
Root Cause
In codex-rs/tui/src/chatwidget.rs, the function handle_elicitation_request_now uses self.thread_id.unwrap_or_default() (the currently active UI thread) instead of params.thread_id (the thread that actually generated the elicitation request):
pub(crate) fn handle_elicitation_request_now(
&mut self,
request_id: AppServerRequestId,
params: McpServerElicitationRequestParams,
) {
...
let thread_id = self.thread_id.unwrap_or_default(); // ← BUG: should use params.thread_id
...
}
The McpServerElicitationRequestParams struct already carries the correct thread_id set by the app-server, but it is ignored throughout the function. The same bug affects:
AppLinkViewParams::from_url_app_server_request— receives wrongthread_idMcpServerElicitationFormRequest::from_app_server_request— receives wrongthread_id- The fallback
ApprovalRequest::McpElicitation— receives wrongthread_id - The
McpServerElicitationRequest::Urlauto-decline path — sendsresolve_elicitationto the wrong thread
Reproduction Steps
- Open a Codex TUI session (thread A) and let it complete a turn
- Start a second review session (thread B) that triggers an MCP elicitation
- The elicitation request from thread B gets routed to thread A because
self.thread_idstill points to A - Thread A's session handler has no pending elicitation for this request, so
resolve_elicitationfails withelicitation request not found - TUI becomes unresponsive
Log Evidence
2026-05-09T06:36:37.565253Z WARN session_loop{thread_id=019e0b71-...}:submission_dispatch{...op="resolve_elicitation"...}: codex_core::session::handlers: failed to resolve elicitation request in session error=elicitation request not found
The elicitation originated from thread 019e0b73 (new review session), but resolve_elicitation was delivered to thread 019e0b71 (old completed session).
Suggested Fix
Replace self.thread_id.unwrap_or_default() with params.thread_id (parsed to ThreadId):
// Before:
let thread_id = self.thread_id.unwrap_or_default();
// After:
let thread_id: ThreadId = params.thread_id.parse()
.unwrap_or_else(|_| self.thread_id.unwrap_or_default());
Affected Code
codex-rs/tui/src/chatwidget.rs—handle_elicitation_request_now(line ~4603)- Same pattern may exist in
handle_request_user_input_nowandhandle_request_permissions_now— should be audited
Introduced By
Commit f9a907aebe — "Support Codex Apps auth elicitations (#19193)"
What steps can reproduce the bug?
- Start a TUI session (Thread A): Open the Codex TUI and complete one or more conversation turns so that Thread A becomes the currently active thread (
self.thread_id = A).
- Open a second session (Thread B): Within the same TUI process, initiate a new operation that creates a second thread — for example, by using
/reviewor/approveon a PR — but keep the TUI UI focus on Thread A.
- Trigger an MCP Elicitation: Have Thread B execute an operation that causes an MCP server to issue an elicitation request (e.g., an MCP tool call that requires connector authentication or user input).
- Observe the routing error: When the TUI receives the elicitation request from Thread B,
handle_elicitation_request_nowincorrectly usesself.thread_id(which is Thread A) instead ofparams.thread_id(which is Thread B).
- Elicitation resolution fails: When the user tries to respond to the elicitation,
resolve_elicitationis sent to Thread A's session handler. Since Thread A has no pending elicitation matching this request, it fails with:
````
failed to resolve elicitation request in session error=elicitation request not found
The TUI then becomes unresponsive.
Key condition: Multiple active sessions exist in the TUI simultaneously, and the currently displayed thread (self.thread_id) differs from the thread that actually generated the elicitation.
What is the expected behavior?
_No response_
Additional information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗