jlcodes99/cockpit-tools · warning

[Provider Store] 忽略异常空账号列表,保留本地缓存: ${cacheKey}

Error message

[Provider Store] 忽略异常空账号列表,保留本地缓存: ${cacheKey}

What it means

console.warn in createProviderAccountStore's fetchAccounts: the service returned an empty account list while the store still holds a non-empty local list and allowNextEmptyAccountList is false. The store treats the empty response as anomalous, keeps local cached accounts, and stops loading — protecting UI state from transient backend emptiness.

Source

Thrown at src/stores/createProviderAccountStore.ts:269

    },

    setCurrentAccountId: (accountId: string | null) => {
      fetchCurrentAccountSeq += 1;
      const currentAccountId = normalizeCurrentAccountId(accountId, get().accounts);
      set({ currentAccountId });
      persistCurrentAccountId(currentAccountId);
    },

    fetchAccounts: async () => {
      const requestId = ++fetchAccountsSeq.current;
      set({ loading: true, error: null });
      try {
        const accounts = await service.listAccounts();
        if (requestId !== fetchAccountsSeq.current) {
          return;
        }
        if (accounts.length === 0 && get().accounts.length > 0 && !allowNextEmptyAccountList) {
          console.warn(`[Provider Store] 忽略异常空账号列表,保留本地缓存: ${cacheKey}`);
          set({ loading: false });
          return;
        }
        allowNextEmptyAccountList = false;
        const mapped = mapAccountsForUnifiedView(accounts);
        set({ accounts: mapped, loading: false });
        persistAccountsCache(mapped);
        await get().fetchCurrentAccountId();
      } catch (e) {
        if (requestId !== fetchAccountsSeq.current) {
          return;
        }
        set({ error: String(e), loading: false });
      } finally {
        if (requestId === fetchAccountsSeq.current) {
          allowNextEmptyAccountList = false;
        }
      }

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Ignore if transient — refetch accounts; a subsequent non-empty list applies normally.
  2. If accounts truly were deleted, perform the deletion through the store so allowNextEmptyAccountList is set first.
  3. Log in again if the provider session expired — an empty list can mask an auth failure.
  4. Inspect the provider listAccounts response (raw network/backend log) for pagination or filter bugs.
  5. Update the integration if the provider API changed its empty-list semantics.
Defensive patterns

Strategy: validation

Validate before calling

const accounts = await service.listAccounts();
if (accounts.length === 0 && get().accounts.length > 0 && !allowNextEmptyAccountList) {
  console.warn(`[Provider Store] ignoring anomalous empty account list: ${cacheKey}`);
  return; // keep cache
}

Type guard

function isNonEmptyAccountList(v: unknown): v is Account[] {
  return Array.isArray(v) && v.length > 0 &&
    v.every(a => typeof a === 'object' && a !== null && 'id' in a);
}

Prevention

When it happens

Trigger: service.listAccounts() resolves to [] while get().accounts.length > 0, allowNextEmptyAccountList is false, and the request is still current (requestId matches).

Common situations: Provider backend restarted or session expired returning empty instead of an auth error; API pagination/filter bug returning zero rows; network proxy stripping the payload; deliberate logout flows bypass this via allowNextEmptyAccountList.

Related errors


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