From d213e523ecc1e71f6c11a967d294340279ec297b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 16:24:20 +0000 Subject: [PATCH] fix(sync): narrow transient-error detection so real errors aren't hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The connectivity-vs-real-error classifier tested the message against /timeout|connect|network|unreachable|refused/i, matching any error whose text happened to include one of those words. A server-side permission error like 'network share access refused' was silently classified as transient, updating only the status dot — the user never saw the actual problem. Tighten the regex to well-known connectivity phrases and lowercase error codes (ENOTFOUND/ECONNREFUSED/etc), using word boundaries so substrings in unrelated messages don't match. --- apps/tauri/src/lib/stores/app.svelte.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/tauri/src/lib/stores/app.svelte.ts b/apps/tauri/src/lib/stores/app.svelte.ts index 65e0238..99d0b08 100644 --- a/apps/tauri/src/lib/stores/app.svelte.ts +++ b/apps/tauri/src/lib/stores/app.svelte.ts @@ -395,7 +395,11 @@ async function triggerSync() { await loadLists(); } catch (e) { const msg = String(e); - const isTransient = /timeout|connect|network|unreachable|refused/i.test(msg); + // Narrow phrases so that a legitimate server-side error containing a + // word like "network" or "refused" in its description isn't silently + // swallowed as an offline blip. Only treat obvious connectivity failures + // as transient. + const isTransient = /(^|\W)(timed? out|timeout|connection (refused|reset|timed out|aborted)|connect error|network (is )?unreachable|no route to host|host (not found|is unreachable)|dns|enotfound|econnrefused|etimedout|ehostunreach|enetunreach)(\W|$)/i.test(msg); syncStatus = isTransient ? "offline" : "error"; // Only show the error banner for non-transient failures; connectivity issues just update the status dot if (!isTransient) error = msg;