diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs
index 3dcd16587cb13d52d318cc580762ef943a917d1b..1ca9b6ece510f0e71e1c338c30fb4a42c08043fe 100644
--- a/src-tauri/src/core/handle.rs
+++ b/src-tauri/src/core/handle.rs
@@ -40,6 +40,12 @@ impl Handle {
     }
   }
 
+  pub fn notice_message(&self, status: String, msg: String) {
+    if let Some(window) = self.get_window() {
+      log_if_err!(window.emit("verge://notice-message", (status, msg)));
+    }
+  }
+
   // update system tray state (clash config)
   pub fn update_systray_clash(&self) -> Result<()> {
     if self.app_handle.is_none() {
diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs
index 096aa45457b8825aa017b7933a193b82450d6bae..1313049bc93424019d6151249f410498282e4fcb 100644
--- a/src-tauri/src/core/mod.rs
+++ b/src-tauri/src/core/mod.rs
@@ -284,9 +284,14 @@ impl Core {
       match Service::set_config(clash_info, config).await {
         Ok(_) => {
           let handle = handle.lock();
-          handle.refresh_clash()
+          handle.refresh_clash();
+          handle.notice_message("set_config::ok".into(), "ok".into());
+        }
+        Err(err) => {
+          let handle = handle.lock();
+          handle.notice_message("set_config::error".into(), format!("{err}"));
+          log::error!(target: "app", "last {err}")
         }
-        Err(err) => log::error!(target: "app", "{err}"),
       }
     });
 
diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs
index ac26d8653b41a4f8ccb3890760b0888e23310b4f..7b62a325129c6814f69b1351127f493d0c02b5bf 100644
--- a/src-tauri/src/core/service.rs
+++ b/src-tauri/src/core/service.rs
@@ -212,8 +212,17 @@ impl Service {
     let mut data = HashMap::new();
     data.insert("path", temp_path.as_os_str().to_str().unwrap());
 
+    macro_rules! report_err {
+      ($i: expr, $e: expr) => {
+        match $i {
+          4 => bail!($e),
+          _ => log::error!(target: "app", $e),
+        }
+      };
+    }
+
     // retry 5 times
-    for _ in 0..5 {
+    for i in 0..5 {
       let headers = headers.clone();
       match reqwest::ClientBuilder::new().no_proxy().build() {
         Ok(client) => {
@@ -223,14 +232,12 @@ impl Service {
               204 => break,
               // 配置有问题不重试
               400 => bail!("failed to update clash config with status 400"),
-              status @ _ => {
-                log::error!(target: "app", "failed to activate clash with status \"{status}\"");
-              }
+              status @ _ => report_err!(i, "failed to activate clash with status \"{status}\""),
             },
-            Err(err) => log::error!(target: "app", "{err}"),
+            Err(err) => report_err!(i, "{err}"),
           }
         }
-        Err(err) => log::error!(target: "app", "{err}"),
+        Err(err) => report_err!(i, "{err}"),
       }
       sleep(Duration::from_millis(500)).await;
     }
diff --git a/src/components/profile/enhanced.tsx b/src/components/profile/enhanced.tsx
index b226fd0ad9ec7d38b61b3e212957b2301cc99807..6c9a5fd083e12051589221b2b101da8d25e44e59 100644
--- a/src/components/profile/enhanced.tsx
+++ b/src/components/profile/enhanced.tsx
@@ -33,7 +33,7 @@ const EnhancedMode = (props: Props) => {
     try {
       await enhanceProfiles();
       mutateLogs();
-      Notice.success("Refresh clash config", 1000);
+      // Notice.success("Refresh clash config", 1000);
     } catch (err: any) {
       Notice.error(err.message || err.toString());
     }
diff --git a/src/components/setting/mods/clash-field-viewer.tsx b/src/components/setting/mods/clash-field-viewer.tsx
index 79875923566441c9d33a07cd2f8b816c0b1331d8..c365a9b5450837f9389949100085818b4c9510e0 100644
--- a/src/components/setting/mods/clash-field-viewer.tsx
+++ b/src/components/setting/mods/clash-field-viewer.tsx
@@ -93,7 +93,7 @@ const ClashFieldViewer = ({ handler }: Props) => {
     try {
       await changeProfileValid([...curSet]);
       mutateProfile();
-      Notice.success("Refresh clash config", 1000);
+      // Notice.success("Refresh clash config", 1000);
     } catch (err: any) {
       Notice.error(err?.message || err.toString());
     }
diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx
index 4361b2fc248e55f38c2aa8576fd3b6c89f19e634..f00ed966f989d5364def62d03c1e83ff64796251 100644
--- a/src/pages/_layout.tsx
+++ b/src/pages/_layout.tsx
@@ -14,6 +14,7 @@ import { getAxios } from "@/services/api";
 import { atomCurrentProfile } from "@/services/states";
 import { getVergeConfig, getProfiles } from "@/services/cmds";
 import { ReactComponent as LogoSvg } from "@/assets/image/logo.svg";
+import Notice from "@/components/base/base-notice";
 import LayoutItem from "@/components/layout/layout-item";
 import LayoutControl from "@/components/layout/layout-control";
 import LayoutTraffic from "@/components/layout/layout-traffic";
@@ -59,6 +60,21 @@ const Layout = () => {
     // update the verge config
     listen("verge://refresh-verge-config", () => mutate("getVergeConfig"));
 
+    // 设置提示监听
+    listen("verge://notice-message", ({ payload }) => {
+      const [status, msg] = payload as [string, string];
+      switch (status) {
+        case "set_config::ok":
+          Notice.success("Refresh clash config");
+          break;
+        case "set_config::error":
+          Notice.error(msg);
+          break;
+        default:
+          break;
+      }
+    });
+
     // set current profile uid
     getProfiles().then((data) => setCurrentProfile(data.current ?? ""));
   }, []);
diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx
index f04a21025fd81ce18b16bed7f02da4b3ebffb370..68391033e558e68cdae0e9332d1dde5e690e6475 100644
--- a/src/pages/profiles.tsx
+++ b/src/pages/profiles.tsx
@@ -133,7 +133,7 @@ const ProfilePage = () => {
       setCurrentProfile(uid);
       mutate("getProfiles", { ...profiles, current: uid }, true);
       mutate("getRuntimeLogs");
-      if (force) Notice.success("Refresh clash config", 1000);
+      // if (force) Notice.success("Refresh clash config", 1000);
     } catch (err: any) {
       Notice.error(err?.message || err.toString());
     }