Skip to content

Treat None litellm_provider as wildcard in _check_provider_match#28523

Merged
oss-pr-review-agent-shin[bot] merged 1 commit into
BerriAI:shin_agent_oss_staging_05_22_2026from
adityasingh2400:fix-cost-calc-provider-match-none-28336
May 22, 2026
Merged

Treat None litellm_provider as wildcard in _check_provider_match#28523
oss-pr-review-agent-shin[bot] merged 1 commit into
BerriAI:shin_agent_oss_staging_05_22_2026from
adityasingh2400:fix-cost-calc-provider-match-none-28336

Conversation

@adityasingh2400

Copy link
Copy Markdown
Contributor

Title

Treat None litellm_provider as wildcard in _check_provider_match

Relevant issues

Fixes #28336

Pre-Submission checklist

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement (details)
  • I have added a screenshot of my new test passing locally
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

Type

Bug Fix

Changes

Problem

_check_provider_match had inconsistent behaviour for a missing
vs. None-valued litellm_provider, even though both mean "no
specific provider constraint":

  • model_info = {} returned True (custom pricing applied)
  • model_info = {"litellm_provider": None} returned False (custom pricing dropped, default provider price used)

register_model reaches the None-valued branch via get_model_info
when a deployment is registered without a provider (e.g. via
Router.add_deployment, which does not forward litellm_provider).
The None then gets persisted into litellm.model_cost, so subsequent
cost lookups for that model intermittently fall through to default
pricing and miscalculate cost / budget enforcement.

Fix

Two minimal, complementary changes in litellm/utils.py:

  1. _check_provider_match now treats model_info.get("litellm_provider") is None
    the same as a missing key, returning True (the wildcard case).
  2. register_model strips litellm_provider=None from the merged
    existing_model before writing into litellm.model_cost, so the
    stored 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/absent litellm_provider
in model_cost means "no provider constraint".

Tests

tests/test_litellm/test_utils.py

  • test_check_provider_match_none_value_matches_any_provider covers the
    _check_provider_match normalisation directly.

tests/test_litellm/test_register_model_custom_pricing.py

  • test_register_model_strips_none_litellm_provider asserts the stored
    entry no longer carries litellm_provider: None and that
    _check_provider_match accepts it for any provider.
  • test_register_model_router_add_deployment_custom_pricing_applies
    exercises the full Router.add_deployment path that originally
    triggered the bug.

@CLAassistant

CLAassistant commented May 21, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed-hq

codspeed-hq Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Congrats! CodSpeed is installed 🎉

🆕 16 new benchmarks were detected.

You will start to see performance impacts in the reports once the benchmarks are run from your default branch.

Detected benchmarks


Open in CodSpeed

@greptile-apps

greptile-apps Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes an inconsistency in _check_provider_match where litellm_provider=None was treated differently from a missing key, causing custom pricing registered via Router.add_deployment to be silently dropped on cost lookups.

  • litellm/utils.py: _check_provider_match now uses model_info.get(\"litellm_provider\") is not None instead of \"litellm_provider\" in model_info, making None and absent keys both behave as wildcards. register_model additionally strips litellm_provider=None from the get_model_info-returned dict before merging, so the bad value is never persisted into model_cost in the first place.
  • Tests: Three new tests cover the unit fix, the strip path (via monkeypatching get_model_info), and the end-to-end Router.add_deployment regression scenario. The monkeypatch test correctly attaches a no-op cache_clear to the fake, matching what _invalidate_model_cost_lowercase_map expects.

Confidence Score: 5/5

Safe 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.

Important Files Changed

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

Comment thread tests/test_litellm/test_register_model_custom_pricing.py
@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: This PR is currently BLOCKED from merge.

Score: 4/5

Why blocked:

  • 1 unresolved reviewer concern (greptile) (unresolved_concern, -1 pts)

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.

Note: This bot is still in beta and might not always work as expected. Please share any feedback via Slack.

@adityasingh2400 adityasingh2400 force-pushed the fix-cost-calc-provider-match-none-28336 branch from 37e8499 to feca33f Compare May 22, 2026 00:07
@adityasingh2400 adityasingh2400 changed the base branch from main to shin_agent_oss_staging_05_21_2026 May 22, 2026 00:07
@adityasingh2400 adityasingh2400 force-pushed the fix-cost-calc-provider-match-none-28336 branch from feca33f to b34a43e Compare May 22, 2026 00:09
@adityasingh2400

Copy link
Copy Markdown
Contributor Author

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
@adityasingh2400 adityasingh2400 force-pushed the fix-cost-calc-provider-match-none-28336 branch from b34a43e to e6db1f7 Compare May 22, 2026 00:41
@adityasingh2400

Copy link
Copy Markdown
Contributor Author

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.

@adityasingh2400

Copy link
Copy Markdown
Contributor Author

@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.

@oss-pr-review-agent-shin oss-pr-review-agent-shin Bot changed the base branch from shin_agent_oss_staging_05_21_2026 to shin_agent_oss_staging_05_22_2026 May 22, 2026 03:05
@oss-pr-review-agent-shin oss-pr-review-agent-shin Bot merged commit 1cfe37d into BerriAI:shin_agent_oss_staging_05_22_2026 May 22, 2026
2 checks passed
@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: Squash-merged into staging branch shin_agent_oss_staging_05_22_2026. Staging PR: #28542


Triage Summary
Fixes a bug in _check_provider_match where litellm_provider=None was treated differently from a missing key, causing custom pricing registered via Router.add_deployment to be silently dropped on cost lookups. Changes litellm/utils.py in two places: the provider match check now uses model_info.get("litellm_provider") is not None instead of "litellm_provider" in model_info, and register_model strips litellm_provider=None before persisting into model_cost. Three new tests cover the unit fix, the strip path via monkeypatching, and the end-to-end Router.add_deployment regression scenario.

Merge Confidence: 5/5 ✅ READY
Ready to ship.

All checks green. Greptile 5/5, no blocking pattern findings, no CircleCI runs (OSS-typical).

Sameerlite pushed a commit that referenced this pull request May 22, 2026
)

Squash-merged by litellm-agent from adityasingh2400's PR.
mateo-berri pushed a commit that referenced this pull request May 22, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants