Summary
When a dynamic provider-model fetch is in flight in the Add Model UI, switching to a different provider before the first request resolves can leak stale results into the new provider's model list.
Why this looks like a bug
PR #12046 intentionally added dynamic model fetching, but the current async state handling still writes fetched models using a stale closure over selectedProvider in gui/src/forms/AddModelForm.tsx.
That means the UI can finish in this state:
- request started for provider A,
- user switches to provider B,
- provider A request resolves late,
- provider A models appear under provider B.
This does not match the intended Add Model UX and can lead to selecting or configuring the wrong model.
Reproduction
- Open the Add Model UI
- Select
OpenAI
- Enter an API key so the refresh icon appears
- Click the refresh icon to fetch provider models
- Before that request resolves, switch the provider to
Anthropic
- Let the original
OpenAI request resolve
Expected
Only the currently selected provider should be allowed to update the fetched model list.
Actual
A late response from the previously selected provider can still populate fetchedModelsList, so stale provider models show up after the provider switch.
Affected code
gui/src/forms/AddModelForm.tsx
The current logic captures selectedProvider.provider at request time, but also uses the same callback closure when deciding whether to commit results.
Validation
I reproduced this locally in a focused GUI test by:
- delaying the
OpenAI fetch,
- switching to
Anthropic before resolution,
- then resolving the original request.
That reproduces the stale-model leak deterministically.
Suggested fix direction
Guard late async results using current-provider tracking (or request token invalidation) before calling setFetchedModelsList(...).
A focused regression test around "switch provider while fetch is in flight" should prevent this from coming back.
Summary
When a dynamic provider-model fetch is in flight in the Add Model UI, switching to a different provider before the first request resolves can leak stale results into the new provider's model list.
Why this looks like a bug
PR #12046 intentionally added dynamic model fetching, but the current async state handling still writes fetched models using a stale closure over
selectedProvideringui/src/forms/AddModelForm.tsx.That means the UI can finish in this state:
This does not match the intended Add Model UX and can lead to selecting or configuring the wrong model.
Reproduction
OpenAIAnthropicOpenAIrequest resolveExpected
Only the currently selected provider should be allowed to update the fetched model list.
Actual
A late response from the previously selected provider can still populate
fetchedModelsList, so stale provider models show up after the provider switch.Affected code
gui/src/forms/AddModelForm.tsxThe current logic captures
selectedProvider.providerat request time, but also uses the same callback closure when deciding whether to commit results.Validation
I reproduced this locally in a focused GUI test by:
OpenAIfetch,Anthropicbefore resolution,That reproduces the stale-model leak deterministically.
Suggested fix direction
Guard late async results using current-provider tracking (or request token invalidation) before calling
setFetchedModelsList(...).A focused regression test around "switch provider while fetch is in flight" should prevent this from coming back.