Skip to content

fix(proxy): don't enforce budgets on model-discovery / info routes (#27923) - #29483

Merged
Sameerlite merged 2 commits into
BerriAI:litellm_oss_stagingfrom
Ar-maan05:fix/27923-budget-model-discovery
Jun 2, 2026
Merged

fix(proxy): don't enforce budgets on model-discovery / info routes (#27923)#29483
Sameerlite merged 2 commits into
BerriAI:litellm_oss_stagingfrom
Ar-maan05:fix/27923-budget-model-discovery

Conversation

@Ar-maan05

@Ar-maan05 Ar-maan05 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #27923

Pre-Submission checklist

  • I have added meaningful tests
  • 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
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Type

🐛 Bug Fix

Changes

When a team, virtual key, organization, or user budget is exhausted, the proxy returned 429 Budget Exceeded on the model-discovery endpoints (GET /v1/models, /models, and the /model/info family). Every OpenAI-compatible client (Open WebUI, Cursor, Aider, Continue, LibreChat, and others) calls GET /v1/models at startup to populate its model list, so an exhausted budget made all models invisible, including free or self-hosted ones, and broke the whole integration rather than just blocking paid inference.

The cause was an inconsistency in litellm/proxy/auth/auth_checks.py. _global_proxy_budget_check already exempted /v1/models and /models, but the entity-level checks in common_checks (team, virtual key, organization, user) ran inside a blanket if not skip_budget_checks: block with no route awareness, so they raised BudgetExceededError on discovery routes. Model listing runs no inference and incurs no spend, so it should never be budget-gated.

The fix sets skip_budget_checks = True in common_checks when the route is a read-only model-discovery route. The exempt set is a small explicit frozenset (MODEL_DISCOVERY_ROUTES) rather than RouteChecks.is_info_route(). This is deliberate: info_routes also contains side-effectful routes such as /health/services, whose handler can send Slack, email, and webhook test messages, and exempting those would let an out-of-budget key keep triggering them. Keeping the set narrow closes that hole while still fixing discovery. Only the budget-skip flag is touched, so authentication, route allow-listing, model-access, and RBAC checks are unchanged, and inference routes stay fully budget-enforced.

The configurable general_settings behavior the issue also proposes (return-all vs return-free-only vs block) is intentionally left out so this PR stays isolated to the bug; it can follow separately.

Regression tests live in tests/test_litellm/proxy/auth/test_auth_checks.py: the six discovery routes are allowed under an exhausted team and user budget, /health/services and /v1/chat/completions still raise BudgetExceededError. The /health/services case is the mutation guard; widening the exemption back to is_info_route() fails it.

Screenshots / Proof of Fix

Run a local proxy against a config that has at least one real model and a master key:

python litellm/proxy/proxy_cli.py --config litellm/proxy/dev_config.yaml --detailed_debug --reload --use_v2_migration_resolver 2>&1 | tee litellm.log

Create a virtual key with a tiny budget so the first real call exhausts it, then drive one real completion to push spend over budget (this hits a live provider and costs a few cents):

KEY=$(curl -s http://localhost:4000/key/generate \
  -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
  -d '{"max_budget": 0.00001, "models": ["<a-model-in-your-config>"]}' | jq -r .key)

curl -s http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"model": "<a-model-in-your-config>", "messages": [{"role": "user", "content": "hi"}]}' > /dev/null

Now the key is over budget. Model discovery succeeds and inference is still blocked:

# returns 200 with the model list (was 429 Budget Exceeded before this fix)
curl -i http://localhost:4000/v1/models -H "Authorization: Bearer $KEY"

# still returns 429 Budget Exceeded
curl -i http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"model": "<a-model-in-your-config>", "messages": [{"role": "user", "content": "hi"}]}'

To see the old behavior for contrast, check out litellm_internal_staging, restart the proxy, and repeat the two curls above: GET /v1/models returns 429 there.

@CLAassistant

CLAassistant commented Jun 2, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where an exhausted team, user, or organization budget caused 429 Budget Exceeded on read-only model-discovery endpoints (/v1/models, /model/info, etc.), breaking OpenAI-compatible clients that call these routes at startup. The fix adds a narrow MODEL_DISCOVERY_ROUTES frozenset in common_checks and sets skip_budget_checks = True before entity budget gates when the request targets one of those routes.

  • litellm/proxy/auth/auth_checks.py: Introduces MODEL_DISCOVERY_ROUTES frozenset and a two-line early assignment of skip_budget_checks = True, leaving all authentication, RBAC, and model-access checks intact; only budget enforcement is bypassed for the listed routes.
  • tests/test_litellm/proxy/auth/test_auth_checks.py: Adds four focused regression tests (team-budget bypass, user-budget bypass, /health/services still blocked, inference routes still blocked), though MODEL_DISCOVERY_ROUTES is re-declared locally instead of imported from the production module.

Confidence Score: 5/5

Safe to merge — the change is a small, well-scoped addition to common_checks that only skips budget enforcement for six read-only, no-spend model-discovery routes.

The production change is minimal: a frozenset constant and a two-line guard that sets an existing boolean flag. Authentication, RBAC, model-access, and route allow-listing are all unaffected. The narrowness of the frozenset (deliberately kept tighter than is_info_route) avoids unintended bypass of side-effectful endpoints. Regression tests cover the key scenarios, and no logic errors or data-path issues were found.

No files require special attention beyond the minor test-maintainability note on test_auth_checks.py.

Important Files Changed

Filename Overview
litellm/proxy/auth/auth_checks.py Adds a narrow MODEL_DISCOVERY_ROUTES frozenset and sets skip_budget_checks=True before entity budget gates when the route is a model-discovery endpoint, fixing #27923 without widening the exemption to side-effectful info routes.
tests/test_litellm/proxy/auth/test_auth_checks.py Adds four regression tests for #27923 (team budget bypass, user budget bypass, /health/services still blocked, inference still blocked) but duplicates MODEL_DISCOVERY_ROUTES as a local list instead of importing the source-of-truth frozenset from auth_checks.

Reviews (2): Last reviewed commit: "fix(proxy): narrow model-discovery budge..." | Re-trigger Greptile

Comment thread litellm/proxy/auth/auth_checks.py Outdated
Comment thread litellm/proxy/auth/auth_checks.py Outdated
@veria-ai

veria-ai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@Ar-maan05

Copy link
Copy Markdown
Contributor Author

@greptile-apps

@Sameerlite
Sameerlite changed the base branch from litellm_internal_staging to litellm_oss_staging June 2, 2026 11:18

@Sameerlite Sameerlite left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

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.

[Bug]: Prevent budget enforcement from blocking model discovery endpoints (allow accessing free models)

3 participants