-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Description
Describe the bug
The PriceDataReload component (ui/litellm-dashboard/src/components/price_data_reload.tsx) polls two admin endpoints every 30 seconds via setInterval:
GET /schedule/model_cost_map_reload/statusGET /model/cost_map/source
It authenticates using accessToken = decoded?.key extracted from the JWT cookie. When a user's virtual key expires, the JWT cookie itself may still be valid (the user stays logged in), but every polling request hits user_api_key_auth which raises:
ProxyException: Authentication Error - Expired Key
This produces continuous HTTP 400 errors in the server logs every 30 seconds, indefinitely, until the user manually refreshes the browser — even though the page appears to function normally.
Reproduction
- Open the Admin UI → Models & Endpoints → Price Data Reload tab
- Leave the browser tab open with an expired virtual key
- Observe repeated
LiteLLM Proxy:ERROR auth_exception_handler.py:78 - user_api_key_auth(): Exception occuredin pod logs every ~30 seconds
Expected behavior
When the polling requests receive HTTP 400/401 (auth failure), the interval should stop. The UI should show a message prompting the user to re-login rather than silently continuing to spam the server.
Logs
06:21:45 - LiteLLM Proxy:ERROR: auth_exception_handler.py:78 - litellm.proxy.proxy_server.user_api_key_auth(): Exception occured -
Requester IP Address: <internal>
litellm.proxy._types.ProxyException
INFO: <ip> - "GET /schedule/model_cost_map_reload/status HTTP/1.1" 400 Bad Request
06:50:39 - LiteLLM Proxy:ERROR: auth_exception_handler.py:78 - litellm.proxy.proxy_server.user_api_key_auth(): Exception occured -
Requester IP Address: <internal>
INFO: <ip> - "GET /model/cost_map/source HTTP/1.1" 400 Bad Request
[repeating every ~30s]
Root cause
In price_data_reload.tsx, the useEffect starts an interval but never checks whether API calls return auth errors:
const interval = setInterval(() => {
fetchReloadStatus(); // throws on HTTP 400, but catch block doesn't stop the interval
fetchSourceInfo();
}, 30000);The catch blocks log the error and set default state but do not clear the interval.
Fix
A fix has been submitted in PR #XXXX. Summary:
- Extract
isAuthError()helper to detect HTTP 400/401 responses - Wrap
fetchReloadStatus/fetchSourceInfowithuseCallback - On auth error, call
stopPolling()which clears the interval and setspollingDisabled = true - Show an
<Alert>banner when polling is paused, prompting re-login useEffectdepends onpollingDisabledso it restarts correctly after fresh login
LiteLLM Version
Reproducible on current main (c89496f).
Environment
- Deployment: Kubernetes (LiteLLM Proxy)
- UI accessed via Admin Dashboard
- Virtual key with expiry set