jlcodes99/cockpit-tools · warning

[AccountStore] 本地缓存空间不足,已自动清理账号缓存并回退为仅内存态。

Error message

[AccountStore] 本地缓存空间不足,已自动清理账号缓存并回退为仅内存态。

What it means

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.

Source

Thrown at src/stores/useAccountStore.ts:62

  }, 0);
}

const accountStoreStorage = createJSONStorage(() => ({
  getItem: (name: string) => {
    try {
      return localStorage.getItem(name);
    } catch (error) {
      console.warn(`[AccountStore] 读取持久化数据失败: ${name}`, error);
      return null;
    }
  },
  setItem: (name: string, value: string) => {
    try {
      localStorage.setItem(name, value);
    } catch (error) {
      if (isQuotaExceededError(error)) {
        if (!accountStoreQuotaWarned) {
          console.warn(
            '[AccountStore] 本地缓存空间不足,已自动清理账号缓存并回退为仅内存态。',
            error
          );
          accountStoreQuotaWarned = true;
        }
        scheduleAccountStoreQuotaRecovery(name);
        return;
      }
      console.warn(`[AccountStore] 写入持久化数据失败: ${name}`, error);
    }
  },
  removeItem: (name: string) => {
    try {
      localStorage.removeItem(name);
    } catch (error) {
      console.warn(`[AccountStore] 删除持久化数据失败: ${name}`, error);
    }
  },

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Clear localStorage for the app origin (or the store's keys) to free quota, then reload — persistence resumes.
  2. Remove unused accounts/providers so serialized state shrinks under the quota.
  3. Audit other localStorage consumers on the origin and evict oversized unrelated keys.
  4. Avoid storing huge tokens/blobs in account state; move them to backend/session storage.
  5. Consider migrating the store to IndexedDB if account datasets are inherently large.

Example fix

// before
setItem: (name, value) => {
  try { localStorage.setItem(name, value); } catch (e) { /* quota warn */ }
}
// after
setItem: (name, value) => {
  try { localStorage.setItem(name, value); }
  catch (e) {
    if (isQuotaExceededError(e)) {
      // shrink payload before persisting
      const trimmed = pruneStaleAccounts(JSON.parse(value));
      try { localStorage.setItem(name, JSON.stringify(trimmed)); }
      catch { /* stay in-memory */ }
    }
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isQuotaExceededError(e: unknown): boolean {
  return e instanceof DOMException && (
    e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
  );
}
// pre-check available headroom
const bytes = new Blob([value]).size;
const current = new Blob([localStorage.getItem(name) ?? '']).size;
if (bytes - current > 2 * 1024 * 1024) scheduleCleanup(); // stay well under ~5MB

Type guard

function isQuotaExceededError(error: unknown): error is DOMException {
  return error instanceof DOMException &&
    (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
}

Try / catch

try {
  localStorage.setItem(name, value);
} catch (error) {
  if (isQuotaExceededError(error)) {
    scheduleAccountStoreQuotaRecovery(name); // prune caches, retry once, else stay in-memory
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/068cdb7f562fcd4b. Report an issue: GitHub.