{"record":{"id":"068cdb7f562fcd4b","repo":"jlcodes99/cockpit-tools","slug":"accountstore-068cdb","errorCode":null,"errorMessage":"[AccountStore] 本地缓存空间不足，已自动清理账号缓存并回退为仅内存态。","messagePattern":"\\[AccountStore\\] 本地缓存空间不足，已自动清理账号缓存并回退为仅内存态。","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/stores/useAccountStore.ts","lineNumber":62,"sourceCode":"  }, 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      }\n      console.warn(`[AccountStore] 写入持久化数据失败: ${name}`, error);\n    }\n  },\n  removeItem: (name: string) => {\n    try {\n      localStorage.removeItem(name);\n    } catch (error) {\n      console.warn(`[AccountStore] 删除持久化数据失败: ${name}`, error);\n    }\n  },","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/stores/useAccountStore.ts#L44-L80","documentation":"localStorage.setItem threw inside the account store's custom storage adapter; the error was a QuotaExceededError. The store logs this warning once (accountStoreQuotaWarned flag), schedules quota recovery (clears cached account entries), and falls back to in-memory-only persistence, so account data will not survive reloads until space frees up.","triggerScenarios":"localStorage is full (typically the ~5MB origin limit) when persisting account store state — large multi-account caches, bulky tokens/payloads, or other keys on the same origin consuming the quota.","commonSituations":"Long-lived installs accumulating many provider accounts with large JWTs; other apps on the same origin (dev server ports) filling localStorage; private-browsing modes with tiny quotas; corrupted giant leftover keys.","solutions":["Clear localStorage for the app origin (or the store's keys) to free quota, then reload — persistence resumes.","Remove unused accounts/providers so serialized state shrinks under the quota.","Audit other localStorage consumers on the origin and evict oversized unrelated keys.","Avoid storing huge tokens/blobs in account state; move them to backend/session storage.","Consider migrating the store to IndexedDB if account datasets are inherently large."],"exampleFix":"// before\nsetItem: (name, value) => {\n  try { localStorage.setItem(name, value); } catch (e) { /* quota warn */ }\n}\n// after\nsetItem: (name, value) => {\n  try { localStorage.setItem(name, value); }\n  catch (e) {\n    if (isQuotaExceededError(e)) {\n      // shrink payload before persisting\n      const trimmed = pruneStaleAccounts(JSON.parse(value));\n      try { localStorage.setItem(name, JSON.stringify(trimmed)); }\n      catch { /* stay in-memory */ }\n    }\n  }\n}","handlingStrategy":"try-catch","validationCode":"function isQuotaExceededError(e: unknown): boolean {\n  return e instanceof DOMException && (\n    e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED'\n  );\n}\n// pre-check available headroom\nconst bytes = new Blob([value]).size;\nconst current = new Blob([localStorage.getItem(name) ?? '']).size;\nif (bytes - current > 2 * 1024 * 1024) scheduleCleanup(); // stay well under ~5MB","typeGuard":"function isQuotaExceededError(error: unknown): error is DOMException {\n  return error instanceof DOMException &&\n    (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');\n}","tryCatchPattern":"try {\n  localStorage.setItem(name, value);\n} catch (error) {\n  if (isQuotaExceededError(error)) {\n    scheduleAccountStoreQuotaRecovery(name); // prune caches, retry once, else stay in-memory\n  } else {\n    throw error;\n  }\n}","preventionTips":["Keep persisted store payloads small: avoid storing raw tokens/blobs; paginate account caches.","Periodically prune unused providers/accounts from persisted state.","Monitor localStorage usage (sum of key sizes) and warn before hitting the ~5MB limit.","Prefer IndexedDB for large datasets; reserve localStorage for small preferences."],"tags":["localstorage","quota","persistence","cache"],"backgroundTag":"localstorage-quota-exceeded","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"}