Skip to content

bug: auto-refresh models overwrites user-curated model list on every Settings open #3465

@expfukck

Description

@expfukck

Problem

After using auto-fetch to get available models from a provider and then manually deleting unwanted models, the deleted models reappear every time the user opens the Settings panel (or restarts and opens Settings).

Root Cause

File: desktop/frontend/src/components/SettingsPanel.tsx, lines 666–692

The auto-refresh useEffect fires every time the "usage" subtab renders and unconditionally replaces the user's curated model list with the full API response:

useEffect(() => {
    if (subtab !== "usage") return;
    // ...
    void backgroundApply(async () => {
      for (const { provider } of candidates) {
        const fetched = await app.FetchProviderModels(provider);
        // ↓↓↓ ALWAYS overwrites with full fetched list ↓↓↓
        await app.SaveProvider({ ...provider, models: fetched, default: currentDefault });
      }
    });
}, [backgroundApply, s.providers, subtab, t]);

Exact bug sequence

  1. User adds a provider → auto-fetch saves all models ✅
  2. User edits provider, removes unwanted models, saves → curated list written to config.toml
  3. User restarts app → config loads correctly with curated list (boot path does NOT fetch) ✅
  4. User opens Settings → "usage" subtabuseEffect fires, autoRefreshKeyRef has reset after restart → fetches ALL models from API → overwrites curated list via SaveProvider

The autoRefreshKeyRef guard only prevents re-fetching within the same session. After any restart or config reload, the ref resets and auto-fetch runs again.

Additional auto-fetch paths with the same issue

  • saveKeyEnvAndAutoRefresh (lines 1064–1097): After saving an API key, immediately fetches and overwrites.
  • refreshModels (lines 1024–1056): Manual "Refresh models" button also does a full replacement (this one is arguably intentional).

Suggested Fix

Option A — Only merge new models (never remove):

const merged = [...new Set([...provider.models, ...fetched])];
// Only save if there are actually new models
if (!sameStringLists(provider.models, merged)) {
  await app.SaveProvider({ ...provider, models: merged, default: currentDefault });
}

Option B — Track user curation with a flag:
Add a modelsUserEdited: boolean field to ProviderView/ProviderEntry. When the user manually edits the model list, set it to true. Auto-refresh skips providers where modelsUserEdited === true.

Option C — Remove auto-refresh, keep manual only:
Remove the auto-refresh useEffect entirely. Users explicitly click "Refresh models" when they want to discover new ones. This is the simplest fix and avoids the issue entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    desktopWails desktop app (desktop/**)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions