From ff9744fd661988450a24d845cb3416ad2af71f7d Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 16 Apr 2026 10:30:28 -0700 Subject: [PATCH] Avoid fatal TUI errors on skills list failure (#18061) Addresses #17951 Problem: The TUI treated skills/list failures as fatal during refresh, so proxy/firewall responses that break plugin discovery could crash the session. Solution: Route startup and refresh skills/list responses through shared graceful handling that logs a warning and keeps the TUI running. --- codex-rs/tui/src/app.rs | 52 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 3fbcd6490..564113156 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -2514,14 +2514,16 @@ impl App { Ok(true) } AppCommandView::ListSkills { cwds, force_reload } => { - let response = app_server - .skills_list(codex_app_server_protocol::SkillsListParams { - cwds: cwds.to_vec(), - force_reload, - per_cwd_extra_user_roots: None, - }) - .await?; - self.handle_skills_list_response(response); + self.handle_skills_list_result( + app_server + .skills_list(codex_app_server_protocol::SkillsListParams { + cwds: cwds.to_vec(), + force_reload, + per_cwd_extra_user_roots: None, + }) + .await, + "failed to refresh skills", + ); Ok(true) } AppCommandView::Compact => { @@ -2595,6 +2597,19 @@ impl App { } } + fn handle_skills_list_result( + &mut self, + result: Result, + failure_message: &str, + ) { + match result { + Ok(response) => self.handle_skills_list_response(response), + Err(err) => { + tracing::warn!("{failure_message}: {err:#}"); + } + } + } + async fn try_resolve_app_server_request( &mut self, app_server: &AppServerSession, @@ -4002,17 +4017,16 @@ impl App { app.enqueue_primary_thread_session(started.session, started.turns) .await?; } - match app_server - .skills_list(codex_app_server_protocol::SkillsListParams { - cwds: vec![app.config.cwd.to_path_buf()], - force_reload: true, - per_cwd_extra_user_roots: None, - }) - .await - { - Ok(response) => app.handle_skills_list_response(response), - Err(err) => tracing::warn!("failed to load skills on startup: {err:#}"), - } + app.handle_skills_list_result( + app_server + .skills_list(codex_app_server_protocol::SkillsListParams { + cwds: vec![app.config.cwd.to_path_buf()], + force_reload: true, + per_cwd_extra_user_roots: None, + }) + .await, + "failed to load skills on startup", + ); // On startup, if Agent mode (workspace-write) or ReadOnly is active, warn about world-writable dirs on Windows. #[cfg(target_os = "windows")]