litellm - ✅(Solved) Fix [Bug]: /v1/models wildcard discovery does not expand team BYOK routes using litellm_credential_name when check_provider_endpoint=true [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#28264Fetched 2026-05-20 03:40:24
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
labeled ×2cross-referenced ×1

Root Cause

without passing the effective team_id. That misses the team-scoped deployment because the router row is keyed by the generated internal model_name, while the public wildcard name is stored in model_info.team_public_model_name.

Fix Action

Fixed

PR fix notes

PR #28284: fix(proxy): hydrate wildcard discovery credentials

Description (problem / solution / changelog)

Relevant issues

Fixes #28264

Linear ticket

<!-- if you are an internal contributor, add the Linear ticket e.g. "Resolves LIT-1234" to magically link the Linear ticket to the GitHub PR -->

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • 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

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

curl -fsS "http://localhost:4006/v1/models?team_id=wildcard-discovery-1779231436" \                                                                         
  -H "Authorization: Bearer sk-demo-wildcard-discovery-master" | jq '.'
{
  "data": [
    {
      "id": "openai/*",
      "object": "model",
      "created": 1677610602,
      "owned_by": "openai"
    },
    {
      "id": "openai/gpt-4o-mini",
      "object": "model",
      "created": 1677610602,
      "owned_by": "openai"
    },
    {
      "id": "openai/gpt-4o",
      "object": "model",
      "created": 1677610602,
      "owned_by": "openai"
    }
  ],
  "object": "list"
}

Full local verification in https://github.com/dibyom/litellm-repro/tree/main/wildcard-discovery-db-mode

<!-- Include screenshots, screen recordings, or log output demonstrating that your changes work as expected. For bug fixes: show reproduction before the fix and passing behavior after. For new features: show the feature working end-to-end. For UI changes: include before/after screenshots. -->

Type

🐛 Bug Fix ✅ Test

Changes

Changed files

  • litellm/proxy/auth/model_checks.py (modified, +34/-3)
  • litellm/proxy/utils.py (modified, +3/-0)
  • tests/test_litellm/proxy/auth/test_model_checks.py (modified, +238/-0)

Code Example

team.models = ["openai/*"]
router model_name = model_name_<team_id>_<uuid>
model_info.team_public_model_name = "openai/*"

---

llm_router.get_model_list(model_name="openai/*")

---

model_list = llm_router.get_model_list(model_name=model)

---

get_known_models_from_wildcard("openai/*", litellm_params=None)

---

litellm_settings:
  check_provider_endpoint: true

---

curl -X POST "$BASE/model/new" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "openai/*",
    "litellm_params": {
      "model": "openai/*",
      "custom_llm_provider": "openai",
      "litellm_credential_name": "my-openai-credential"
    },
    "model_info": {
      "team_id": "<team_id>"
    }
  }'

---

3. Ensure the team allows the wildcard model:

---

4. Call `/v1/models` with a team key:

---

5. Observe that only literal wildcard rows are returned — no concrete `openai/<model>` entries.

6. Compare with `check_provider_endpoint: false` — the static catalog fallback makes it appear to work.

### Relevant log output

---

### What part of LiteLLM is this about?

Proxy

### What LiteLLM version are you on?

Observed on v1.83.10. The relevant code path still exists in v1.85.0-rc.2.

### Suggested fix direction

1. Pass the effective `team_id` into wildcard expansion so the router can resolve team-scoped deployments:

---

2. Before calling provider model discovery, hydrate `litellm_credential_name` into the effective params. This mirrors the existing router credential resolution:
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

/v1/models wildcard expansion has two related issues for team-scoped BYOK wildcard models.

1. Team-scoped wildcard deployment is not found

A team BYOK wildcard can be stored like this:

team.models = ["openai/*"]
router model_name = model_name_<team_id>_<uuid>
model_info.team_public_model_name = "openai/*"

But wildcard expansion looks up the route with:

llm_router.get_model_list(model_name="openai/*")

without passing the effective team_id. That misses the team-scoped deployment because the router row is keyed by the generated internal model_name, while the public wildcard name is stored in model_info.team_public_model_name.

The relevant code is in litellm/proxy/auth/model_checks.py in _get_wildcard_models():

model_list = llm_router.get_model_list(model_name=model)

Router.get_model_list() already accepts an optional team_id parameter and uses it to look up team_pattern_routers[team_id], but the caller never passes it.

2. LiteLLM falls back to generic provider expansion without hydrating credentials

When no deployment is found, LiteLLM falls back to:

get_known_models_from_wildcard("openai/*", litellm_params=None)

Even when a wildcard deployment IS found, provider discovery (_get_valid_models_from_provider_api in litellm/utils.py) only extracts api_key and api_base from litellm_params — it never resolves litellm_credential_name via CredentialAccessor.get_credential_values().

The correct credential resolution pattern already exists in the Router (e.g., during request routing), but is not applied on the discovery path.

With check_provider_endpoint: false, the fallback uses the static local provider catalog, so /v1/models appears to expand correctly. With check_provider_endpoint: true, the provider model-list call goes out without auth and returns no models.

Expected behavior: /v1/models should expand openai/* into concrete OpenAI model IDs when the team has access to a valid team-scoped BYOK wildcard deployment.

Actual behavior: /v1/models returns only literal openai/* rows and no concrete openai/<model> rows.

This affects model discovery. It does not necessarily mean inference fails with stored credentials.

Steps to Reproduce

  1. Configure LiteLLM proxy with provider endpoint discovery enabled:
litellm_settings:
  check_provider_endpoint: true
  1. Add a wildcard model to a team using a stored credential via the /model/new API:
curl -X POST "$BASE/model/new" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "openai/*",
    "litellm_params": {
      "model": "openai/*",
      "custom_llm_provider": "openai",
      "litellm_credential_name": "my-openai-credential"
    },
    "model_info": {
      "team_id": "<team_id>"
    }
  }'

LiteLLM internally stores this as a team-scoped deployment with a generated model_name (e.g., model_name_<team_id>_<uuid>) and sets model_info.team_public_model_name = "openai/*".


3. Ensure the team allows the wildcard model:

```json
{
  "team_id": "<team_id>",
  "models": ["openai/*"]
}
  1. Call /v1/models with a team key:
curl -fsS "$BASE/v1/models?team_id=$TEAM_ID&return_wildcard_routes=true" \
  -H "Authorization: Bearer $VIRTUAL_KEY" \
  | jq '[.data[]?.id | select(startswith("openai/"))] | {count: length, sample: .[:10]}'
  1. Observe that only literal wildcard rows are returned — no concrete openai/<model> entries.

  2. Compare with check_provider_endpoint: false — the static catalog fallback makes it appear to work.

Relevant log output

No stack trace observed. The endpoint succeeds but wildcard discovery returns no concrete provider models.

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on?

Observed on v1.83.10. The relevant code path still exists in v1.85.0-rc.2.

Suggested fix direction

  1. Pass the effective team_id into wildcard expansion so the router can resolve team-scoped deployments:
llm_router.get_model_list(model_name=model, team_id=team_id)
  1. Before calling provider model discovery, hydrate litellm_credential_name into the effective params. This mirrors the existing router credential resolution:
credential_name = litellm_params.get("litellm_credential_name")
if credential_name:
    credential_values = CredentialAccessor.get_credential_values(credential_name)
    litellm_params.update(credential_values)
    litellm_params.pop("litellm_credential_name", None)
  1. Suggested regression tests:
    • check_provider_endpoint=true, team-scoped wildcard with litellm_credential_name: /v1/models returns concrete model IDs
    • check_provider_endpoint=true, global wildcard with litellm_credential_name: provider discovery receives hydrated credentials
    • check_provider_endpoint=false: wildcard still expands via static catalog
    • /v1/models response does not expose credential values

Twitter / LinkedIn details

N/A

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING