Repository navigation
fix(proxy): surface DB deployments dropped at load instead of a WARNING log - #41280
devin-ai-integration[bot] wants to merge 5 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… is dropped Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Greptile SummaryThis PR records deployments rejected during router loading, exposes those failures to proxy administrators, improves missing-model errors, and makes DB loading order deterministic
Confidence Score: 3/5The PR is not safe to merge until DB loading remains compatible with existing callers and removed dropped deployments are reconciled The new sort raises before loading rows that omit Files Needing Attention: litellm/proxy/proxy_server.py, litellm/router.py, litellm/proxy/route_llm_request.py
|
| Filename | Overview |
|---|---|
| litellm/proxy/proxy_server.py | Sorts DB deployments and exposes dropped records, but breaks row-like callers lacking created_at and returns unmasked exception text |
| litellm/proxy/route_llm_request.py | Adds dropped-model errors and suppresses read-through, which makes stale dropped state affect recovery |
| litellm/router.py | Tracks dropped deployments but does not reconcile dropped-only IDs when their persisted rows disappear |
| litellm/types/router.py | Adds a small immutable value type for dropped deployment details |
| tests/test_litellm/proxy/test_proxy_server.py | Covers administrator visibility and deterministic ordering but does not cover existing row-like fixtures or stale cleanup |
| tests/test_litellm/proxy/test_route_llm_request.py | Covers dropped versus unknown request errors but not stale-state read-through recovery |
| tests/test_litellm/router_strategy/test_complexity_router.py | Verifies failed complexity-router registration and successful same-ID cleanup |
Reviews (1): Last reviewed commit: "fix(proxy): keep live model groups routa..." | Re-trigger Greptile
| added_models = 0 | ||
| ## ADD MODEL LOGIC | ||
| for m in db_models: | ||
| for m in sorted(db_models, key=lambda m: (m.created_at or datetime.min, m.model_id)): |
There was a problem hiding this comment.
Sorting breaks row-like callers
Sorting reads created_at before processing, so existing row-like callers without that attribute raise immediately and no deployments are loaded
Knowledge Base Used: Proxy configuration and deployment
| - The deleted deployment | ||
| - OR None (if deleted deployment not found) | ||
| """ | ||
| if id in self.dropped_deployments: | ||
| self.dropped_deployments = MappingProxyType( |
| dropped_deployments: Final = ( | ||
| [asdict(dropped_deployment) for dropped_deployment in llm_router.dropped_deployments.values()] | ||
| if _user_has_admin_view(user_api_key_dict) | ||
| else None | ||
| ) |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
TLDR
Problem this solves:
How it solves it:
dropped_deployments)/model/infoshows them to proxy admins with the reasoncreated_at, model_idorderUser Flow
Before: an admin upgrades a proxy with two DB-stored complexity routers using custom
tier_definitions, no license, and one of them silently disappearsSTORE_MODEL_IN_DB=Trueand no config change"model": "complexity-two"Invalid model name passed in model=complexity-two. Call /v1/models to view available models for your key.data, with no hint it was ever configuredAfter: the same restart still enforces the cap, but the admin and the caller can both see why the model is unavailable
STORE_MODEL_IN_DB=Trueand no config change"model": "complexity-two"model=complexity-two is configured on the proxy but failed to load. Ask your proxy admin to check /model/info for the reason.dropped_deploymentslist with the model name, id and the full cap error textRelevant issues
Affected release
regression in v1.101.0 (the cap landed in #39468 and #39674; existing DB rows over it were dropped silently)
Linear ticket
Resolves LIT-7812
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Setup: proxy started with
store_model_in_db: true,master_key: sk-1234, noLITELLM_LICENSE.complexity-one(complexity router with customtier_definitions) was created through/model/new.complexity-two(same shape) was inserted straight intoLiteLLM_ProxyModelTableto simulate a row that existed before the upgrade.Before (d392928)
Admin model info
curl -s http://localhost:4000/model/info -H 'Authorization: Bearer sk-1234' | jq '{models: [.data[].model_name], dropped_deployments}'{"models": ["repro-base", "complexity-one"], "dropped_deployments": null}Request to the dropped model
curl -s -i http://localhost:4000/v1/chat/completions -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{"model":"complexity-two","messages":[{"role":"user","content":"hi"}]}'Proxy log
grep -m1 "Error upserting deployment complexity-two" repro_proxy.logAfter (4a6b7d0)
Admin model info
curl -s http://localhost:4000/model/info -H 'Authorization: Bearer sk-1234' | jq '{models: [.data[].model_name], dropped_deployments}'{ "models": ["repro-base", "complexity-one"], "dropped_deployments": [ { "model_name": "complexity-two", "model_id": "complexity-two-id", "error": "At most 1 auto-router(s) with operator-defined tier_definitions or an operator-written classifier prompt can be registered but this would make 2. Use the shipped tiers and classifier prompt for this router or remove an existing router with tier_definitions or its own classifier prompt." } ] }Request to the dropped model
curl -s -i http://localhost:4000/v1/chat/completions -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{"model":"complexity-two","messages":[{"role":"user","content":"hi"}]}'Proxy log
grep -m1 "Error upserting deployment complexity-two" repro_proxy_fixed2.logType
🐛 Bug Fix
Caveats (if any)
Medium
auto_routerlicense feature or to remove a routerdropped_deploymentslives in memory per worker, so it reflects that worker's last DB reloadLow
created_atchanges which router wins the slot on proxies that happened to load the newer one first/model/infobylitellm_model_idfor a dropped id still returns the plain not-found responseFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/acb50415376344159a4ad4d8f56deda2
Open in Devin Desktop: https://app.devin.ai/desktop/session/acb50415376344159a4ad4d8f56deda2?variant=devin