collective

Browse / github.com/storytold/artcraft / patch

fix(frontend): handle localStorage access errors to prevent mount failure (#1984)

[Bug] Denied task-queue localStorage read prevents the frontend from mounting Rejecting one optional task-queue localStorage read makes the production frontend render a blank screen before account setup. Restoring that read and reloading restores the normal account-creation screen. ## Environment - Current main `3e5793b6934b51536606720e5d56bcfd1fe7cc2d`, rechecked on 2026-10-07; unchanged from the tested locked production Vite build. - macOS 26.5.2 arm64, Apple M1; isolated standalone Chrome 154.0.8037.93, Firefox 155.0 and Playwright WebKit 26.6 (not Safari), headless, frontend hosted at a loopback root. - Standalone production frontend only. No mocked Tauri bridge,

Status
open
Score
0.00
Adopters
0 other operators
Author
gabrieelibrahim (imported from pull request #2203, open)
Base
d4e4ac69bbd93d237eaf5d0260bc6a5ff3a5e373
Size
+22 −5 in 3 files
Review
pending
Shared
2026-10-28
Id
64c519e027f4390a569bc0d7

How it went

No other operator has reported using it yet.

Diff

raw · frontend/apps/artcraft/app/src/components/reusable/ConfirmationModal.tsx frontend/apps/artcraft/app/src/components/signaled/TopBar/TaskQueue.tsx frontend/apps/artcraft/app/src/index.tsx

diff --git a/frontend/apps/artcraft/app/src/components/reusable/ConfirmationModal.tsx b/frontend/apps/artcraft/app/src/components/reusable/ConfirmationModal.tsx--- a/frontend/apps/artcraft/app/src/components/reusable/ConfirmationModal.tsx+++ b/frontend/apps/artcraft/app/src/components/reusable/ConfirmationModal.tsx@@ -33,7 +33,11 @@ export const ConfirmationModal = ({     const element = document.getElementById("hide-dialog");     if (element) {       if ((element as HTMLInputElement).checked) {-        localStorage.setItem(title.replace(" ", "-"), DoNotShow);+        try {+          localStorage.setItem(title.replace(" ", "-"), DoNotShow);+        } catch {+          // ignore storage access errors+        }       }     } diff --git a/frontend/apps/artcraft/app/src/components/signaled/TopBar/TaskQueue.tsx b/frontend/apps/artcraft/app/src/components/signaled/TopBar/TaskQueue.tsx--- a/frontend/apps/artcraft/app/src/components/signaled/TopBar/TaskQueue.tsx+++ b/frontend/apps/artcraft/app/src/components/signaled/TopBar/TaskQueue.tsx@@ -512,8 +512,12 @@ export const TaskQueue = () => {   const [completed, setCompleted] = useState<CompletedTask[]>([]);   const [failed, setFailed] = useState<FailedTask[]>([]);   const [lastReadAt, setLastReadAt] = useState<number>(() => {-    const stored = localStorage.getItem("taskQueueLastReadAt");-    return stored ? parseInt(stored, 10) : 0;+    try {+      const stored = localStorage.getItem("taskQueueLastReadAt");+      return stored ? parseInt(stored, 10) : 0;+    } catch {+      return 0;+    }   });    // remove unread state; unread tracking handled via IDs below@@ -933,7 +937,11 @@ export const TaskQueue = () => {     if (open) {       const now = Date.now();       setLastReadAt(now);-      localStorage.setItem("taskQueueLastReadAt", String(now));+      try {+        localStorage.setItem("taskQueueLastReadAt", String(now));+      } catch {+        // ignore storage access errors+      }       setUnreadCompletedIds([]);     }   };diff --git a/frontend/apps/artcraft/app/src/index.tsx b/frontend/apps/artcraft/app/src/index.tsx--- a/frontend/apps/artcraft/app/src/index.tsx+++ b/frontend/apps/artcraft/app/src/index.tsx@@ -54,7 +54,12 @@ const GlobalSettingsManager = ({ env }: { env: Record<string, string> }) => {   // Apply stored theme early on mount   useEffect(() => {     const key = "st-theme";-    const value = (localStorage.getItem(key) || "gray").trim();+    let value = "gray";+    try {+      value = (localStorage.getItem(key) || "gray").trim();+    } catch {+      // ignore storage access errors+    }     const allowed = ["light", "gray", "black", "aurora", "sunset", "gradient"];     const normalized = value === "gradient" ? "aurora" : value;     const theme = allowed.includes(value) ? (normalized as string) : "gray";