Fix/credential list stale on add model - #26600
Conversation
…own stale
After a credential was added/updated/deleted in the "LLM Credentials" tab,
ModelsAndEndpointsView's credentialsList (passed to the "Add Model" dropdown)
was never refreshed because CredentialsPanel called refetch() on its own
observer only.
Replace with queryClient.invalidateQueries({ queryKey: credentialsKeys.all })
— the established cross-component invalidation pattern used throughout the
codebase (accessGroupKeys, projectKeys, cloudZeroSettingsKeys, etc.) — which
marks the shared React Query cache entry as stale and triggers a refetch for
all active subscribers, including ModelsAndEndpointsView.
Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
keys?.keys || [] creates a fresh [] reference on every render, which triggers useFilterLogic's useEffect (dep: keys), which calls setFilteredKeys, which re-renders the parent, which creates another new [] — maximum update depth exceeded. Stabilize the reference with useMemo(() => keys?.keys ?? [], [keys]) so the effect only fires when the actual server data changes. Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
…RL in dev The hardcoded localhost:4000 default in networking.tsx made it impossible to run the frontend dev server against a port-forwarded K8s backend without manually setting localStorage. Add NEXT_PUBLIC_LITELLM_PROXY_URL as the top-level override in defaultProxyBaseUrl. When set, all API calls (including the getUiConfig discovery request) go to that URL. Falls back to the existing localhost:4000 / NEXT_PUBLIC_USE_REWRITES logic unchanged. Also fix getUiConfig to use proxyBaseUrl instead of defaultProxyBaseUrl, so that litellm_worker_url set via localStorage is also respected for the initial discovery request. Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
…PUBLIC_LITELLM_PROXY_URL
updateProxyBaseUrl had its own copy of the localhost:4000 fallback.
When getUiConfig received proxy_base_url=null from the backend it used
that hardcoded value, immediately overwriting the correct URL set via
NEXT_PUBLIC_LITELLM_PROXY_URL.
Fix: use the module-level defaultProxyBaseUrl (which already respects
NEXT_PUBLIC_LITELLM_PROXY_URL) as the fallback inside updateProxyBaseUrl.
Also remove the dead Form.useForm() instance in CredentialsPanel that
was never connected to any <Form form={...}>, causing the Ant Design
"Instance created by useForm is not connected" console warning.
Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
Ant Design Select does not accept null as an option value.
Change { value: null, label: "None" } → { value: "", label: "None" }
and remove initialValue={null} from the Form.Item (no initial selection
is correctly represented by undefined, not null). The submit handler
already deletes litellm_credential_name from params when absent, so
the empty string is handled safely.
Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
…ges from credential fix These networking.tsx changes were only needed for the K8s port-forward dev workflow. They are unrelated to the credential list staleness fix and add unnecessary scope to this PR. Reverting to upstream baseline. Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
…ranch Already covered by fix/virtual-keys-infinite-rerender. Keep credential fix PR scope focused on the stale credential list bug only. Co-Authored-By: Claude Sonnet 4 (1M context) <noreply@anthropic.com>
…ist-stale-on-add-model
Greptile SummaryFixes a stale credentials dropdown on the Add Model tab. After any mutation in the LLM Credentials panel, the Existing Credentials select now updates immediately by using Confidence Score: 5/5Safe to merge — targeted, well-tested fix using an established codebase pattern. No P0 or P1 findings. The No files require special attention.
|
| Filename | Overview |
|---|---|
| ui/litellm-dashboard/src/app/(dashboard)/hooks/credentials/useCredentials.ts | Exports credentialsKeys so consumers can reference the canonical query key for cross-component cache invalidation. |
| ui/litellm-dashboard/src/components/model_add/credentials.tsx | Replaces per-observer refetch() with queryClient.invalidateQueries(credentialsKeys.all) on add/update/delete; removes dead Form.useForm() instance and Form import. |
| ui/litellm-dashboard/src/components/add_model/AddModelForm.tsx | Changes the "None" credential option from value: null to value: "" and removes initialValue={null} to fix the Ant Design v5 warning; empty string is already correctly skipped in the submit handler. |
| ui/litellm-dashboard/src/components/model_add/credentials.test.tsx | Removes stale refetch stubs, mocks AddCredentialModal for easier form submission in tests, and adds a new test verifying invalidateQueries is called on credential add. |
Sequence Diagram
sequenceDiagram
participant U as User
participant CP as CredentialsPanel
participant QC as QueryClient (shared cache)
participant UC1 as useCredentials (CredentialsPanel)
participant UC2 as useCredentials (ModelsAndEndpointsView)
participant AMF as AddModelForm dropdown
U->>CP: Add / Edit / Delete credential
CP->>QC: invalidateQueries({ queryKey: ["credentials"] })
QC-->>UC1: mark stale → background refetch
QC-->>UC2: mark stale → background refetch
UC2-->>AMF: fresh credential list
AMF-->>U: dropdown updated ✓
Reviews (1): Last reviewed commit: "Merge branch 'BerriAI:litellm_internal_s..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…e-on-add-model # Conflicts: # ui/litellm-dashboard/src/components/model_add/credentials.tsx
|
@yassin-berriai @mateo-berri @Sameerlite gentle nudge on this one. The Existing Credentials dropdown on the Add Model tab goes stale after you add, edit, or delete a credential in the LLM Credentials panel, so you have to reload the page before your change shows up. This invalidates and refetches the list so the select updates immediately. Open since late April with no maintainer review yet. Could you take a look? |
PR: fix(ui): credential list stays stale on Add Model page after adding a credential
Relevant issues
Pre-Submission checklist
npm run testpasses for affected files (5/5)@greptileaiand get Confidence Score ≥ 4/5 before requesting maintainer reviewType
🐛 Bug Fix
Changes
Root cause
After adding, editing, or deleting a credential in the LLM Credentials tab,
the Existing Credentials dropdown on the Add Model tab does not reflect
the change until a full page refresh.
CredentialsPanelcallsrefetch()on its ownuseQueryobserver after eachmutation, which refreshes the panel's own list. However,
ModelsAndEndpointsViewholds a separate
useCredentials()subscription and passes the result down ascredentialsList → AddModelTab → AddModelForm → AntdSelect options. Thatsubscription is never notified, so the dropdown stays stale:
Reproduce:
Fix
Replace
refetch()withqueryClient.invalidateQueries({ queryKey: credentialsKeys.all }),the established cross-component cache invalidation pattern used throughout this
codebase (
accessGroupKeys,projectKeys,cloudZeroSettingsKeys,keyKeys, …).invalidateQueriesmarks the shared React Query cache entry as stale and triggersa background refetch for all active subscribers — including
ModelsAndEndpointsView— so the dropdown updates immediately after any mutation.credentialsKeysis exported fromuseCredentials.tsso consumers can referencethe canonical query key without duplicating the string.
Additional fixes in the same files
credentials.tsx— remove deadForm.useForm()instance that was neverconnected to any
<Form form={...}>, causing the Ant Design console warning"Instance created by
useFormis not connected to any Form element".AddModelForm.tsx— fix Ant Design console warning"
valuein Select options should not benull": the "None" option usedvalue: null, which Ant Design v5 rejects. Changed tovalue: ""and removedthe corresponding
initialValue={null}fromForm.Item(no-selection iscorrectly represented by
undefined). The submit handler already deleteslitellm_credential_namefrom params when the value is absent, so the emptystring is handled safely.
Files changed
ui/litellm-dashboard/src/app/(dashboard)/hooks/credentials/useCredentials.tscredentialsKeysso consumers can reference the canonical query keyui/litellm-dashboard/src/components/model_add/credentials.tsxrefetch()withinvalidateQuerieson all three mutation handlers; remove deadForm.useForm()+Formimportui/litellm-dashboard/src/components/add_model/AddModelForm.tsxnulloption value in credentialAntdSelect; removeinitialValue={null}ui/litellm-dashboard/src/components/model_add/credentials.test.tsxrefetchstub; exportcredentialsKeysin mock; add test verifyinginvalidateQueriesis called on credential add