fix(ui): credential list stays stale on Add Model page after adding a credential - #25851
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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryFixes a bug where the Existing Credentials dropdown on the Add Model tab stayed stale after mutations in the LLM Credentials panel. Confidence Score: 5/5Safe to merge — the fix is minimal, follows established patterns in this codebase, and all remaining findings are P2 or lower. The invalidation approach is the canonical React Query cross-component pattern already used throughout the codebase. The empty-string Select value is correctly handled by the existing skip-guard in the submit handler. No P0 or P1 issues found. 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 ["credentials"] prefix for cache invalidation without duplicating the string literal. |
| ui/litellm-dashboard/src/components/model_add/credentials.tsx | Replaces all three local refetch calls with invalidateQueries on the shared cache prefix; removes the disconnected Form.useForm instance. Straightforward and correct. |
| ui/litellm-dashboard/src/components/add_model/AddModelForm.tsx | Changes the None option value from null to empty string and removes initialValue={null}; the submit handler already skips empty-string values at line 54, so no credential is sent when None is selected. |
| ui/litellm-dashboard/src/components/model_add/credentials.test.tsx | Mocks AddCredentialModal to bypass Ant Design form internals, removes stale refetch stub, adds a focused test asserting invalidateQueries is called with ["credentials"] after a credential add. |
Sequence Diagram
sequenceDiagram
participant CP as CredentialsPanel
participant QC as QueryClient
participant MAV as ModelsAndEndpointsView
participant API as Backend
Note over CP,MAV: Before fix
CP->>API: create credential
CP->>CP: refetch (local only)
MAV-->>MAV: stale list remains
Note over CP,MAV: After fix
CP->>API: create credential
CP->>QC: invalidateQueries(credentialsKeys.all)
QC->>API: refetch for CredentialsPanel subscriber
QC->>API: refetch for ModelsAndEndpointsView subscriber
MAV-->>MAV: updated list received
Reviews (1): Last reviewed commit: "revert(ui): remove VirtualKeysTable useM..." | Re-trigger Greptile
|
@Sameerlite Is this issue fixed by someone else? Or should I change the branch and make another pull request? |
|
Sorry about that, can you please reraise this with litellm_internal_staging branch as base? |
|
@Sameerlite #26600 Here is the new pr. #25784 this pr is also closed earlier, and here is the new one |
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