Treat None litellm_provider as wildcard in _check_provider_match#28523
Conversation
|
|
Congrats! CodSpeed is installed 🎉
You will start to see performance impacts in the reports once the benchmarks are run from your default branch.
|
Greptile SummaryThis PR fixes an inconsistency in
Confidence Score: 5/5Safe to merge — the changes are minimal, narrowly scoped, and do not alter behaviour for any model that already has a valid non-None litellm_provider. Both changes in utils.py are one-liners that only affect the None/absent case; _update_dictionary already skips None values so there is no risk of re-introducing the bad value through the merge step. Test coverage now directly exercises the previously-uncovered strip path via monkeypatching. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/utils.py | Two complementary fixes: _check_provider_match now treats litellm_provider=None identically to a missing key (wildcard), and register_model strips litellm_provider=None from the merged existing_model before writing into model_cost. Both changes are minimal, logically correct, and _update_dictionary already skips None values so no double-write risk exists. |
| tests/test_litellm/test_register_model_custom_pricing.py | Three new tests added: a basic registration test, a monkeypatched test that exercises the strip branch in register_model with a fake get_model_info returning litellm_provider=None, and an end-to-end Router.add_deployment regression test. The monkeypatch test correctly adds a no-op cache_clear to satisfy _invalidate_model_cost_lowercase_map. |
| tests/test_litellm/test_utils.py | Adds test_check_provider_match_none_value_matches_any_provider directly verifying the _check_provider_match fix for None and absent litellm_provider. Clean, focused unit test. |
Reviews (2): Last reviewed commit: "Treat None litellm_provider as wildcard ..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
🤖 litellm-agent: This PR is currently BLOCKED from merge. Score: 4/5 ❌ Why blocked:
Details: Score docked for: 1 unresolved reviewer concern (greptile). 2 checks also red on neighboring PRs (test-server-root-path (/api/v1), test-server-root-path (/llmproxy)) — infra-wide noise, no penalty. Fix the issues above and push an update — the bot will re-review automatically.
|
37e8499 to
feca33f
Compare
feca33f to
b34a43e
Compare
|
Retargeted from main to shin_agent_oss_staging_05_21_2026 to satisfy the Guard main branch policy for external contributors. Rebased my single commit onto the staging branch so the diff stays minimal (no merge commits). New head is b34a43ed and contains the same litellm/utils.py + tests change as before. Happy to retarget again if a different staging branch is preferred. |
_check_provider_match returned True when the litellm_provider key was absent from the model_cost entry but False when present with value None, even though both mean "no specific provider constraint". Combined with register_model merging litellm_provider=None into model_cost, this made custom pricing intermittently bypass providers in router setups. Normalise the None case so the two paths behave identically. Fixes BerriAI#28336
b34a43e to
e6db1f7
Compare
|
Thanks for the catch. I added test_register_model_strips_none_litellm_provider_from_get_model_info, which monkeypatches get_model_info to return a populated dict with litellm_provider=None (the exact failure mode the strip was added to handle). It asserts the persisted entry never carries litellm_provider=None, that the rest of the get_model_info metadata still flows through, and that _check_provider_match accepts the entry for any provider. A future regression removing the strip from register_model will now fail this test. |
|
@greptileai please re-review. The test thoroughness gap was addressed with test_register_model_strips_none_litellm_provider_from_get_model_info in e6db1f7 which monkeypatches get_model_info to exercise the strip branch. |
1cfe37d
into
BerriAI:shin_agent_oss_staging_05_22_2026
|
🤖 litellm-agent: Squash-merged into staging branch Triage Summary Merge Confidence: 5/5 ✅ READY All checks green. Greptile 5/5, no blocking pattern findings, no CircleCI runs (OSS-typical). |
* fix(anthropic): handle empty streaming tool calls (#28549) Co-authored-by: shin-berri <shin-laptop@berri.ai> Co-authored-by: yuneng-jiang <yuneng@berri.ai> * [Feature][Bug Fix] Decouple Azure OpenAI Deployment ID from model name via base_model to fix gpt5 model routing (#28490) * feat(azure): decouple deployment ID from model name via base_model Azure OpenAI deployments have arbitrary names (deployment IDs) that may not match the underlying model. Previously, model-type detection (o-series, gpt-5, etc.) relied on substring matching against the deployment name, causing misrouted configs and rejected params when deployment names were non-standard (e.g. 'my-deployment-id' for gpt-5.2). This change extends the existing base_model field to drive model-type detection, config selection, supported param resolution, and param mapping throughout the Azure call path: - _get_azure_config() uses base_model for is_o_series/is_gpt_5 checks - get_provider_chat_config() threads base_model for Azure - get_supported_openai_params() accepts and uses base_model - get_optional_params() accepts base_model and passes it to all Azure config method calls (get_supported_openai_params, map_openai_params) - azure.py completion handler uses base_model for GPT-5 detection - Config internal methods (e.g. is_model_gpt_5_2_model) now receive base_model so features like logprobs are correctly enabled Fully backward compatible - when base_model is unset, behavior is identical. Existing o_series/ and gpt5_series/ prefix workarounds continue to work. Usage in proxy config: model_list: - model_name: my-gpt5 litellm_params: model: azure/my-deployment-id model_info: base_model: azure/gpt-5.2 Fixes: non-standard deployment names like 'prefix-gpt-5.2' rejecting logprobs/top_logprobs despite the underlying model supporting them. * Addressing Greptile comments. * gemini-3.1-flash-lite pricing (#27933) * feat(model_prices): add gemini-3.1-flash-lite pricing with standard/batch/flex/priority tiers * fix pricing * add service tier --------- Co-authored-by: shin-berri <shin-laptop@berri.ai> * fix(openai-responses): strip Anthropic cache_control from Responses API requests (#28431) Squash-merged by litellm-agent from cwang-otto's PR. * Treat None litellm_provider as wildcard in _check_provider_match (#28523) Squash-merged by litellm-agent from adityasingh2400's PR. * fix greptile * fix: use _azure_detection_model in default Azure branch of get_supported_openai_params Co-authored-by: Yassin Kortam <yassin@berri.ai> * fix(openai-responses): strip cache_control on compact endpoint as well Co-authored-by: Yassin Kortam <yassin@berri.ai> --------- Co-authored-by: Felipe Garé <90070734+FelipeRodriguesGare@users.noreply.github.com> Co-authored-by: shin-berri <shin-laptop@berri.ai> Co-authored-by: yuneng-jiang <yuneng@berri.ai> Co-authored-by: withomasmicrosoft <withomas@microsoft.com> Co-authored-by: mubashir1osmani <mubashir.osmani777@gmail.com> Co-authored-by: cwang-otto <chengxuan.wang@ottotheagent.com> Co-authored-by: Aditya Singh <60082699+adityasingh2400@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Yassin Kortam <yassin@berri.ai>
Title
Treat None litellm_provider as wildcard in _check_provider_matchRelevant issues
Fixes #28336
Pre-Submission checklist
tests/test_litellm/directory, Adding at least 1 test is a hard requirement (details)make test-unitType
Bug Fix
Changes
Problem
_check_provider_matchhad inconsistent behaviour for a missingvs.
None-valuedlitellm_provider, even though both mean "nospecific provider constraint":
model_info = {}returnedTrue(custom pricing applied)model_info = {"litellm_provider": None}returnedFalse(custom pricing dropped, default provider price used)register_modelreaches theNone-valued branch viaget_model_infowhen a deployment is registered without a provider (e.g. via
Router.add_deployment, which does not forwardlitellm_provider).The
Nonethen gets persisted intolitellm.model_cost, so subsequentcost lookups for that model intermittently fall through to default
pricing and miscalculate cost / budget enforcement.
Fix
Two minimal, complementary changes in
litellm/utils.py:_check_provider_matchnow treatsmodel_info.get("litellm_provider") is Nonethe same as a missing key, returning
True(the wildcard case).register_modelstripslitellm_provider=Nonefrom the mergedexisting_modelbefore writing intolitellm.model_cost, so thestored entry never carries the misleading
None.Either fix alone resolves the symptom; both together make the two code
paths converge on the same invariant: a
None/absentlitellm_providerin
model_costmeans "no provider constraint".Tests
tests/test_litellm/test_utils.pytest_check_provider_match_none_value_matches_any_providercovers the_check_provider_matchnormalisation directly.tests/test_litellm/test_register_model_custom_pricing.pytest_register_model_strips_none_litellm_providerasserts the storedentry no longer carries
litellm_provider: Noneand that_check_provider_matchaccepts it for any provider.test_register_model_router_add_deployment_custom_pricing_appliesexercises the full
Router.add_deploymentpath that originallytriggered the bug.