thread_view: Add fallback error handling for connect failures (#50063)

Following up from https://github.com/zed-industries/zed/pull/50061: when
connecting to an ACP adapter fails before any thread is active, errors
would not display in the Agent Panel. Falling back to
`handle_load_error` to show the error UI properly as it already handles
this.

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Added fallback error handling for connect failures in the Agent Panel
This commit is contained in:
Kunall Banerjee authored and GitHub committed 2026-02-25 09:25:14 +01:00
1 parent ca066cbefd
commit 3d5c8a53ae
1 file changed
+64
+64
View File
@@ -609,6 +609,8 @@ impl AcpServerView {
this.handle_load_error(err, window, cx);
} else if let Some(active) = this.active_thread() {
active.update(cx, |active, cx| active.handle_any_thread_error(err, cx));
} else {
this.handle_load_error(err, window, cx);
}
cx.notify();
})
@@ -3092,6 +3094,38 @@ pub(crate) mod tests {
});
}
#[gpui::test]
async fn test_connect_failure_transitions_to_load_error(cx: &mut TestAppContext) {
init_test(cx);
let (thread_view, cx) = setup_thread_view(FailingAgentServer, cx).await;
thread_view.read_with(cx, |view, cx| {
let title = view.title(cx);
assert_eq!(
title.as_ref(),
"Error Loading Codex CLI",
"Tab title should show the agent name with an error prefix"
);
match &view.server_state {
ServerState::LoadError(LoadError::Other(msg)) => {
assert!(
msg.contains("Invalid gzip header"),
"Error callout should contain the underlying extraction error, got: {msg}"
);
}
other => panic!(
"Expected LoadError::Other, got: {}",
match other {
ServerState::Loading(_) => "Loading (stuck!)",
ServerState::LoadError(_) => "LoadError (wrong variant)",
ServerState::Connected(_) => "Connected",
}
),
}
});
}
#[gpui::test]
async fn test_auth_required_on_initial_connect(cx: &mut TestAppContext) {
init_test(cx);
@@ -3602,6 +3636,36 @@ pub(crate) mod tests {
}
}
struct FailingAgentServer;
impl AgentServer for FailingAgentServer {
fn logo(&self) -> ui::IconName {
ui::IconName::AiOpenAi
}
fn name(&self) -> SharedString {
"Codex CLI".into()
}
fn connect(
&self,
_root_dir: Option<&Path>,
_delegate: AgentServerDelegate,
_cx: &mut App,
) -> Task<gpui::Result<(Rc<dyn AgentConnection>, Option<task::SpawnInTerminal>)>> {
Task::ready(Err(anyhow!(
"extracting downloaded asset for \
https://github.com/zed-industries/codex-acp/releases/download/v0.9.4/\
codex-acp-0.9.4-aarch64-pc-windows-msvc.zip: \
failed to iterate over archive: Invalid gzip header"
)))
}
fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
#[derive(Clone)]
struct StubSessionList {
sessions: Vec<AgentSessionInfo>,