From 9667d7882a7da1a0f5d3aa7b12c5ecec8a34250e Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Thu, 20 Nov 2025 18:28:11 -0300
Subject: [PATCH] extensions_ui: Improve error message when extensions fail to
load (#43197)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Release Notes:
- extensions UI: Improved the feedback message for when extensions are
not being displayed due to a fetch error caused by lack of connection.
---
crates/extensions_ui/src/extensions_ui.rs | 51 +++++++++++++++++------
1 file changed, 39 insertions(+), 12 deletions(-)
diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs
index 657a39f09e6465042f5f1a5d113bdfa6e61c43ce..e35c90b6104b44bd6dbf3fe86aeaf84f122c04ca 100644
--- a/crates/extensions_ui/src/extensions_ui.rs
+++ b/crates/extensions_ui/src/extensions_ui.rs
@@ -293,6 +293,7 @@ pub struct ExtensionsPage {
workspace: WeakEntity,
list: UniformListScrollHandle,
is_fetching_extensions: bool,
+ fetch_failed: bool,
filter: ExtensionFilter,
remote_extension_entries: Vec,
dev_extension_entries: Vec>,
@@ -353,6 +354,7 @@ impl ExtensionsPage {
workspace: workspace.weak_handle(),
list: scroll_handle,
is_fetching_extensions: false,
+ fetch_failed: false,
filter: ExtensionFilter::All,
dev_extension_entries: Vec::new(),
filtered_remote_extension_indices: Vec::new(),
@@ -479,6 +481,7 @@ impl ExtensionsPage {
cx: &mut Context,
) {
self.is_fetching_extensions = true;
+ self.fetch_failed = false;
cx.notify();
let extension_store = ExtensionStore::global(cx);
@@ -534,17 +537,31 @@ impl ExtensionsPage {
};
let fetch_result = remote_extensions.await;
- this.update(cx, |this, cx| {
+
+ let result = this.update(cx, |this, cx| {
cx.notify();
this.dev_extension_entries = dev_extensions;
this.is_fetching_extensions = false;
- this.remote_extension_entries = fetch_result?;
- this.filter_extension_entries(cx);
- if let Some(callback) = on_complete {
- callback(this, cx);
+
+ match fetch_result {
+ Ok(extensions) => {
+ this.fetch_failed = false;
+ this.remote_extension_entries = extensions;
+ this.filter_extension_entries(cx);
+ if let Some(callback) = on_complete {
+ callback(this, cx);
+ }
+ Ok(())
+ }
+ Err(err) => {
+ this.fetch_failed = true;
+ this.filter_extension_entries(cx);
+ Err(err)
+ }
}
- anyhow::Ok(())
- })?
+ });
+
+ result?
})
.detach_and_log_err(cx);
}
@@ -1277,7 +1294,9 @@ impl ExtensionsPage {
let has_search = self.search_query(cx).is_some();
let message = if self.is_fetching_extensions {
- "Loading extensions..."
+ "Loading extensions…"
+ } else if self.fetch_failed {
+ "Failed to load extensions. Please check your connection and try again."
} else {
match self.filter {
ExtensionFilter::All => {
@@ -1304,7 +1323,17 @@ impl ExtensionsPage {
}
};
- Label::new(message)
+ h_flex()
+ .py_4()
+ .gap_1p5()
+ .when(self.fetch_failed, |this| {
+ this.child(
+ Icon::new(IconName::Warning)
+ .size(IconSize::Small)
+ .color(Color::Warning),
+ )
+ })
+ .child(Label::new(message))
}
fn update_settings(
@@ -1673,9 +1702,7 @@ impl Render for ExtensionsPage {
}
if count == 0 {
- this.py_4()
- .child(self.render_empty_state(cx))
- .into_any_element()
+ this.child(self.render_empty_state(cx)).into_any_element()
} else {
let scroll_handle = self.list.clone();
this.child(