fix(sync): narrow transient-error detection so real errors aren't hidden

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.
This commit is contained in:
Claude 2026-04-17 16:24:20 +00:00
parent 0fc1f16c9d
commit d213e523ec
No known key found for this signature in database

View file

@ -395,7 +395,11 @@ async function triggerSync() {
await loadLists(); await loadLists();
} catch (e) { } catch (e) {
const msg = String(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"; syncStatus = isTransient ? "offline" : "error";
// Only show the error banner for non-transient failures; connectivity issues just update the status dot // Only show the error banner for non-transient failures; connectivity issues just update the status dot
if (!isTransient) error = msg; if (!isTransient) error = msg;