fix(router): stop spurious "Could not identify azure model" ERROR spam - #33620
fix(router): stop spurious "Could not identify azure model" ERROR spam#33620devin-ai-integration[bot] wants to merge 2 commits into
Conversation
…oyment name resolves from the cost map get_router_model_info already falls back to resolving the azure deployment's model name against the model cost map when base_model is unset — and for deployments named after real azure models (e.g. azure/gpt-4o) that resolution returns correct max tokens and costs. The unconditional ERROR was therefore spurious for exactly the deployments that need no operator action, and on busy proxies it logs thousands of times per day per multi-deployment group. Log at debug when the fallback entry carries usable limits/costs (membership alone is not enough: Router init auto-registers every deployment name as a zeroed stub), keep the ERROR otherwise. Fixes #33172
…ack gate Review follow-up: token-limit fields used 'is not None' while the cost field used '> 0' — a cost-map entry explicitly storing 0 limits could suppress the error log without carrying usable resolution data. All three checks now require a positive value.
🤖 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:
|
Greptile SummaryThis PR reduces log noise in the Router's Azure base-model resolution path: when an Azure deployment's model name already exists in the cost map with real limits/costs, the previous unconditional
Confidence Score: 4/5Safe to merge; the change is purely to log level and does not alter model resolution or cost-tracking behavior. The fix is narrowly scoped to a logging branch. The only gap is that litellm/router.py — the
|
| Filename | Overview |
|---|---|
| litellm/router.py | Adds a pre-check before the existing azure base_model logging: looks up the deployment's name in the cost map and only logs at ERROR when the entry lacks usable limits/costs; known models are downgraded to DEBUG. Logic is sound; minor gap — output_cost_per_token is not included in the "usable" gate. |
| tests/test_litellm/test_router.py | Adds three focused regression tests covering the three cases: known azure name resolves without ERROR, unmappable name still logs ERROR, and explicit base_model takes precedence. Tests use monkeypatch + local cost map to avoid network calls and isolate global state. |
Reviews (1): Last reviewed commit: "fix(router): use consistent positive che..." | Re-trigger Greptile
| _fallback_resolves = ( | ||
| (_fallback_entry.get("max_input_tokens") or 0) > 0 | ||
| or (_fallback_entry.get("max_tokens") or 0) > 0 | ||
| or (_fallback_entry.get("input_cost_per_token") or 0) > 0 | ||
| ) |
There was a problem hiding this comment.
The
_fallback_resolves gate checks max_input_tokens, max_tokens, and input_cost_per_token, but omits output_cost_per_token. A model entry that carries only a positive output_cost_per_token (zero input cost, no explicit token limit) would be misclassified as a zeroed stub and still emit the spurious ERROR. While uncommon for Azure models today, this is a latent edge-case that the same condition is supposed to guard against.
| _fallback_resolves = ( | |
| (_fallback_entry.get("max_input_tokens") or 0) > 0 | |
| or (_fallback_entry.get("max_tokens") or 0) > 0 | |
| or (_fallback_entry.get("input_cost_per_token") or 0) > 0 | |
| ) | |
| _fallback_resolves = ( | |
| (_fallback_entry.get("max_input_tokens") or 0) > 0 | |
| or (_fallback_entry.get("max_tokens") or 0) > 0 | |
| or (_fallback_entry.get("input_cost_per_token") or 0) > 0 | |
| or (_fallback_entry.get("output_cost_per_token") or 0) > 0 | |
| ) |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
This one is an internal logging-noise fix in the Router's azure The behavior is pinned by 3 focused regression tests that fail before the fix and pass after: a name that resolves to a usable cost-map entry no longer logs ERROR (drops to debug), a genuinely unmappable deployment name still logs ERROR, and an explicit If you can drop Azure OpenAI creds into this session I can add the live log before/after as well Full walkthrough and test report: https://app.devin.ai/sessions/2a3db9e7f3234370988a77b458d0a202 |

Relevant issues
Fixes #33172
Internal replacement branch for OSS PR #33292 by Mihidum Hettiyahandi (@mihidumh); original authorship is preserved on the commits
Linear ticket
Pre-Submission checklist
Screenshots / Proof of Fix
This is an internal logging-noise fix in the Router's Azure base_model resolution. When an
azure/deployment's model name already resolves to a real cost-map entry, the router logged a spuriousCould not identify azure model ...at ERROR on every call, which spammed logs for correctly-configured deploymentsThe behavior is pinned by three focused regression tests at commit
9dc23c7e3a, each of which fails on the pre-fix tree and passes here:They cover: a known azure deployment name resolves from the cost map without an ERROR log; a genuinely unmappable name still logs the ERROR; and an explicit
base_modelstill takes precedenceNote on live-proxy proof: reproducing the log line end-to-end needs real Azure OpenAI credentials and a deployment, which were not available in this session. The regression tests exercise the exact resolution/logging branch that changed
Type
🐛 Bug Fix
Changes
In the Azure base_model fallback path the router derives
_azure_fallback_key(prefixingazure/when missing), looks up the cost-map entry, and treats it as usable only when at least one ofmax_input_tokens,max_tokens, orinput_cost_per_tokenis positive. A usable entry means the name is understood, so the message is logged at debug instead of error; genuinely unmappable names keep the original ERROR. This guards against the Router's zeroed auto-registered stubs being treated as real resolutions, and uses consistent positive checks across the gateFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/2a3db9e7f3234370988a77b458d0a202