{"record":{"id":"76187109e17ddb7d","repo":"jlcodes99/cockpit-tools","slug":"accountstore-name","errorCode":null,"errorMessage":"[AccountStore] 读取持久化数据失败: ${name}","messagePattern":"\\[AccountStore\\] 读取持久化数据失败: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/stores/useAccountStore.ts","lineNumber":52,"sourceCode":"  setTimeout(() => {\n    try {\n      localStorage.removeItem(storageKey);\n      localStorage.removeItem(LEGACY_ACCOUNTS_CACHE_KEY);\n      localStorage.removeItem(LEGACY_CURRENT_ACCOUNT_CACHE_KEY);\n    } catch (error) {\n      console.warn('[AccountStore] 清理超限缓存失败:', error);\n    } finally {\n      accountStoreQuotaCleanupScheduled = false;\n    }\n  }, 0);\n}\n\nconst accountStoreStorage = createJSONStorage(() => ({\n  getItem: (name: string) => {\n    try {\n      return localStorage.getItem(name);\n    } catch (error) {\n      console.warn(`[AccountStore] 读取持久化数据失败: ${name}`, error);\n      return null;\n    }\n  },\n  setItem: (name: string, value: string) => {\n    try {\n      localStorage.setItem(name, value);\n    } catch (error) {\n      if (isQuotaExceededError(error)) {\n        if (!accountStoreQuotaWarned) {\n          console.warn(\n            '[AccountStore] 本地缓存空间不足，已自动清理账号缓存并回退为仅内存态。',\n            error\n          );\n          accountStoreQuotaWarned = true;\n        }\n        scheduleAccountStoreQuotaRecovery(name);\n        return;\n      }","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/stores/useAccountStore.ts#L34-L70","documentation":"The zustand persist custom storage's getItem wraps localStorage.getItem in try/catch. When reads fail, it warns with the storage key name and returns null so zustand falls back to the initial state instead of crashing store creation.","triggerScenarios":"localStorage.getItem throws on store initialization — storage disabled by browser policy, Safari private mode, security restrictions in embedded webviews, or corrupted storage access after a quota error.","commonSituations":"App opened in private/incognito browsing; enterprise browsers with third-party storage blocked; webview embedders that disable DOM storage.","solutions":["Return null (already done) so the store boots with defaults — verify initial state is sensible","Detect storage availability at startup and switch to an in-memory storage adapter","Ask users to allow site data / exit private mode if persistence matters","Persist to an alternative backend (IndexedDB, Tauri fs) when localStorage is unavailable"],"exampleFix":"// before\ngetItem: (name: string) => {\n  try { return localStorage.getItem(name); }\n  catch (error) { console.warn(`[AccountStore] 读取持久化数据失败: ${name}`, error); return null; }\n}\n// after\ngetItem: (name: string) => {\n  try { return localStorage.getItem(name); }\n  catch (error) { console.warn(`[AccountStore] 读取持久化数据失败: ${name}`, error); return memoryStore.get(name) ?? null; }\n}","handlingStrategy":"fallback","validationCode":"function safeGetItem(name: string): string | null {\n  try { return localStorage.getItem(name); } catch { return null; }\n}","typeGuard":"function hasStorage(s: unknown): s is Storage {\n  try {\n    const st = s as Storage;\n    const k = '__probe__';\n    st.setItem(k, k); st.removeItem(k);\n    return true;\n  } catch { return false; }\n}","tryCatchPattern":"getItem: (name: string) => {\n  try { return localStorage.getItem(name); }\n  catch (error) {\n    console.warn(`[AccountStore] 读取持久化数据失败: ${name}`, error);\n    return null; // zustand falls back to initial state\n  }\n}","preventionTips":["Provide an in-memory or IndexedDB storage adapter when localStorage throws","Ensure store initial state is complete enough to run without persisted data","Detect private-mode storage restrictions at startup and inform the user","Never let a read failure crash store creation — always return null"],"tags":["localstorage","zustand-persist","read-failure"],"backgroundTag":"localstorage-access-denied","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}