Skip to content

fix(proxy): expand all-proxy-models sentinel in direct access lookup - #31153

Merged
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fix_all_proxy_models_visibility
Jun 24, 2026
Merged

mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fix_all_proxy_models_visibility

Conversation

@mubashir1osmani

@mubashir1osmani mubashir1osmani commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #22791

Linear ticket

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

Screenshots / Proof of Fix

Repro: as an admin, create an internal user provisioned with "All Proxy Models" and no team, then list models as that user (the exact call the Models + Endpoints page makes).

# 1) provision the user with the all-proxy-models sentinel
curl -s -X POST http://localhost:4000/user/new \
  -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
  -d '{"user_role":"internal_user","models":["all-proxy-models"]}'
# -> user_id ..., key sk-..., models ["all-proxy-models"]

# 2) list models as that user (Models + Endpoints page request)
curl -s "http://localhost:4000/v2/model/info?include_team_models=true" \
  -H "Authorization: Bearer sk-USERKEY" | jq '.total_count'

Before this change the second call returns total_count = 0 (empty Models + Endpoints page) even though the same proxy has 37 models and the admin sees all 37. After the change the user sees the full set of non-team proxy models, matching what the Playground / model dropdown already showed (that path goes through get_key_models, which already expands the sentinel, which is why the two views disagreed).

verified locally:
Screenshot 2026-06-23 at 6 36 38 PM

Type

🐛 Bug Fix

Changes

A user provisioned with "All Proxy Models" stores the literal all-proxy-models sentinel in user.models. On the read path behind /v1/model/info and /v2/model/info, get_direct_access_models looped over user.models and looked each entry up as a real model_name via llm_router.get_model_list(model_name=...). The sentinel matches no deployment, so the lookup returned nothing, every model got direct_access=false, and with no team membership _filter_models_to_user_accessible dropped the entire list. The result was an empty Models + Endpoints page for exactly the users who were granted access to everything.

The fix expands the sentinel to all non-team deployment ids via get_model_ids(exclude_team_models=True), the same call the PROXY_ADMIN branch in the caller already uses. Because both /v1/model/info and /v2/model/info share _populate_team_access_on_models, this fixes both. An empty user.models still resolves to no direct access, matching get_key_models semantics.

Tests in tests/test_litellm/proxy/proxy_server/test_team_model_name_translation.py cover the sentinel expansion in get_direct_access_models, the unchanged explicit-model path, and the full _populate_team_access_on_models -> _filter_models_to_user_accessible chain for an internal user with no teams; the chain test fails on the pre-fix code and passes after.

A user provisioned with "All Proxy Models" stores the literal
"all-proxy-models" sentinel in user.models. get_direct_access_models looked
that string up as a real model_name via get_model_list, which matched no
deployment, so /v2/model/info marked every model direct_access=false and the
Models + Endpoints page rendered empty for such users when they have no teams.
The model dropdown / Playground worked because get_key_models already expands
the sentinel to the full proxy model list, hence the inconsistency in the
report.

Expand the sentinel to all non-team deployment ids via
get_model_ids(exclude_team_models=True), the same call the PROXY_ADMIN branch
in the caller already uses. This fixes both /v1/model/info and /v2/model/info
since they share _populate_team_access_on_models. Empty user.models stays "no
direct access" to match get_key_models semantics.

Fixes #22791
@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes a bug where internal users provisioned with the all-proxy-models sentinel in user.models saw an empty Models + Endpoints page. The sentinel was passed to llm_router.get_model_list(model_name=...), which matched no real deployment, so every model got direct_access=False and was then dropped by the filter.

  • get_direct_access_models now short-circuits on the sentinel and delegates to llm_router.get_model_ids(exclude_team_models=True), the same call already used by the PROXY_ADMIN branch in _populate_team_access_on_models.
  • The non-sentinel path is refactored to an equivalent walrus-operator list comprehension, and three focused mock tests cover the sentinel, explicit-model, and full access-chain scenarios.

Confidence Score: 5/5

Safe to merge — the change is tightly scoped to one helper function and both affected endpoints, the fix reuses the exact same router call already trusted in the admin branch, and a model_validator in LiteLLM_UserTable guarantees models is never None.

The logic change is minimal and correct: the sentinel check is guarded by the existing Pydantic validator that coerces a DB NULL to [], so the in test is always safe. The non-sentinel list comprehension is semantically identical to the original loop. Three new mock-only unit tests directly target the regression path and would fail against the pre-fix code, and the PR description includes a concrete reproduction script. No existing tests were weakened.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/proxy_server.py Expands the all-proxy-models sentinel in get_direct_access_models by returning llm_router.get_model_ids(exclude_team_models=True) when the sentinel is detected, matching the PROXY_ADMIN branch behavior; also refactors the non-sentinel path to an equivalent list comprehension.
tests/test_litellm/proxy/proxy_server/test_team_model_name_translation.py Adds three new mock-only unit tests: sentinel expansion, explicit model name path, and a full integration-style chain through _populate_team_access_on_models → _filter_models_to_user_accessible for an internal user with no teams; no real network calls.

Reviews (1): Last reviewed commit: "fix(proxy): expand all-proxy-models sent..." | Re-trigger Greptile

@codecov

codecov Bot commented Jun 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri mateo-berri 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!

Comment on lines -11506 to +11516
direct_access_models: List[str] = []
for model in user_db_object.models:
deployments = llm_router.get_model_list(model_name=model)
if deployments is not None:
for deployment in deployments:
model_id = deployment.get("model_info", {}).get("id", None)
if model_id is not None:
direct_access_models.append(model_id)
return direct_access_models
return [
model_id
for model in user_db_object.models
for deployment in (llm_router.get_model_list(model_name=model) or [])
if (model_id := deployment.get("model_info", {}).get("id", None)) is not None
]

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.

wow this is way better. nice

@mateo-berri
mateo-berri merged commit e0c8a6b into litellm_internal_staging Jun 24, 2026
123 of 124 checks passed
@mateo-berri
mateo-berri deleted the litellm_fix_all_proxy_models_visibility branch June 24, 2026 05:23
@ishaan-berri ishaan-berri mentioned this pull request Jun 25, 2026
9 of 13 tasks
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]: LiteLLM Proxy UI does not show all models

2 participants