Skip to content

fix(router): restore BYOK key injection for vector store endpoints with team-scoped deployments - #25746

Merged
yuneng-berri merged 5 commits into
litellm_internal_stagingfrom
litellm_vector-store-team-byok-model-none
Apr 24, 2026
Merged

fix(router): restore BYOK key injection for vector store endpoints with team-scoped deployments #25746
yuneng-berri merged 5 commits into
litellm_internal_stagingfrom
litellm_vector-store-team-byok-model-none

Conversation

@shivamrawat1

Copy link
Copy Markdown
Contributor

Relevant issues

Vector store endpoints (/v1/vector_stores) pass model=None to the router. After the team model routing fix in #25148,
map_team_model(None, team_id) returned None unchanged, so the router never resolved a team deployment and forwarded requests without
injecting BYOK credentials.

Cause
map_team_model only returned team_model_name when a matching team deployment was found — but when team_model_name is None (no model
in the request), it short-circuited and returned None even though a valid team deployment existed. The router therefore couldn't find
the deployment or inject the API key.

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

Type

🐛 Bug Fix
✅ Test

Changes

When team_model_name is None, instead of returning None, return the matched team deployment's team_public_model_name (falling back to
model_name). This gives the router a concrete model name to route against and inject BYOK credentials. The existing non-None path is
untouched, so the sibling-deployment load-balancing fix from #25148 is unaffected.

…th team-scoped deployments

When vector store endpoints (POST/GET /v1/vector_stores) are called, model=None
is passed to the router. map_team_model(None, team_id) was returning None
unchanged after the team model routing fix in #25148, so the router never found
the team's BYOK deployment and forwarded requests without the API key.

Fix: when team_model_name is None, return the matched deployment's
team_public_model_name (or model_name fallback) so the router can route to it
and inject the BYOK credentials. Does not affect the sibling-deployment
load-balancing fix since that only applies when a non-None model is passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@shivamrawat1
shivamrawat1 requested a review from a team April 15, 2026 04:02
@vercel

vercel Bot commented Apr 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 15, 2026 4:16am

Request Review

@CLAassistant

CLAassistant commented Apr 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes BYOK credential injection for vector store endpoints (e.g. /v1/vector_stores) that pass model=None to the router. The root cause was that map_team_model returned None unchanged when team_model_name was None, so the router never resolved a team-scoped deployment and skipped credential injection. The fix widens the type signature to Optional[str] and, when team_model_name is None, returns the first matching team deployment's team_public_model_name (falling back to model_name) so the router has a concrete name to route against and inject BYOK credentials. The existing non-None path is untouched.

Confidence Score: 4/5

Fix is logically correct for the stated use case; safe to merge with the caveat that multi-deployment teams may see non-deterministic credential injection.

The logic change is minimal and well-scoped: only the None branch is new, and the existing non-None path is untouched. The only open concern (first-match ambiguity for teams with multiple deployments) is a P2 edge case unlikely to affect current users. No tests cover the new branch (flagged in a prior thread), which slightly reduces confidence.

litellm/router.py — specifically the new team_model_name is None branch in map_team_model and how the returned model name interacts with downstream routing for teams that have multiple deployments.

Important Files Changed

Filename Overview
litellm/router.py Adds a None-model branch in map_team_model so vector store endpoints (which pass model=None) can still resolve a team deployment and get BYOK credentials injected; type signature widened from str to Optional[str].

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Vector store request\nmodel=None, team_id=T] --> B{team_id set?}
    B -- No --> C[Skip map_team_model\nroute normally]
    B -- Yes --> D[map_team_model\nteam_model_name=None, team_id=T]
    D --> E[get_model_list\nmodel_name=None\nreturns ALL models]
    E --> F{Any model with\nteam_id == T?}
    F -- No --> G[return None\nBYOK NOT injected]
    F -- Yes --> H[return team_public_model_name\nor model_name]
    H --> I[data model = resolved name]
    I --> J[router routes call\ninjects BYOK credentials]
Loading

Reviews (4): Last reviewed commit: "Merge branch 'litellm_internal_staging' ..." | Re-trigger Greptile

Comment thread litellm/router.py
Comment on lines +8348 to +8354
if team_model_name is None:
# No model was specified (e.g. vector store endpoints).
# Return the deployment's public model name so the router
# can route to it and inject the BYOK API key.
return model.get("model_info", {}).get(
"team_public_model_name"
) or model.get("model_name")

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.

P1 No test for the new None-model path

git diff HEAD~1 HEAD shows only litellm/router.py changed — no test file was added or modified in tests/test_litellm/. The presubmission checklist marks the test requirement as done, but the new branch (team_model_name is None) has zero coverage. The sibling test test_arouter_test_team_model at tests/test_litellm/test_router.py:373 only covers the non-None case. A minimal test would be:

def test_map_team_model_none_model_returns_team_deployment():
    router = litellm.Router(
        model_list=[{
            "model_name": "gpt-4o",
            "litellm_params": {"model": "openai/gpt-4o"},
            "model_info": {
                "team_id": "team-1",
                "team_public_model_name": "team-gpt4",
            },
        }]
    )
    result = router.map_team_model(team_model_name=None, team_id="team-1")
    assert result == "team-gpt4"

@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@veria-ai

veria-ai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Low: Minor routing logic extension for team-scoped BYOK

This PR modifies map_team_model in litellm/router.py to accept None as the model name parameter, enabling vector store endpoints (which don't carry a model in the request) to resolve team-scoped deployments for BYOK credential injection. The team_id filtering remains intact, scoping results to the authenticated caller's team. No new attack surface identified.


Status: 0 open
Risk: 2/10

Posted by Veria AI · 2026-04-24T00:33:57.983Z

@veria-ai

veria-ai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Low: No security issues found

This PR widens the map_team_model signature to accept Optional[str] and adds a fallback path for when no model is specified (vector store endpoints). The change is scoped to team-owned deployments filtered by the authenticated user's team_id, so there's no cross-team access or authorization bypass. The single existing caller still passes data["model"] which is guaranteed non-None at that call site due to an earlier guard.


Status: 0 open
Risk: 2/10

Posted by Veria AI · 2026-04-24T00:36:03.271Z

@shivamrawat1
shivamrawat1 temporarily deployed to integration-postgres April 24, 2026 00:41 — with GitHub Actions Inactive
@shivamrawat1
shivamrawat1 temporarily deployed to integration-postgres April 24, 2026 00:42 — with GitHub Actions Inactive
@shivamrawat1
shivamrawat1 temporarily deployed to integration-postgres April 24, 2026 00:42 — with GitHub Actions Inactive
@shivamrawat1
shivamrawat1 temporarily deployed to integration-postgres April 24, 2026 00:42 — with GitHub Actions Inactive
@shivamrawat1
shivamrawat1 temporarily deployed to integration-postgres April 24, 2026 00:42 — with GitHub Actions Inactive
@veria-ai

veria-ai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Low: Narrow change to team model resolution

This PR modifies map_team_model to accept Optional[str] for the model name parameter and adds a branch that returns the first matching team deployment when no model is specified. The team_id filtering is preserved, maintaining cross-team isolation. The new None code path is not currently reachable from the only production call site (route_llm_request.py:471), which early-returns for model-less endpoints before reaching map_team_model. No security issues identified.


Status: 0 open
Risk: 2/10

Posted by Veria AI · 2026-04-24T00:42:47.712Z

@gitguardian

gitguardian Bot commented Apr 24, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29203065 Triggered JSON Web Token e982fe8 tests/test_litellm/proxy/test_litellm_pre_call_utils.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

1 similar comment
@gitguardian

gitguardian Bot commented Apr 24, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29203065 Triggered JSON Web Token e982fe8 tests/test_litellm/proxy/test_litellm_pre_call_utils.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@yuneng-berri
yuneng-berri merged commit 654b688 into litellm_internal_staging Apr 24, 2026
103 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_vector-store-team-byok-model-none branch April 24, 2026 01:16
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…am-byok-model-none

  fix(router): restore BYOK key injection for vector store endpoints with team-scoped deployments
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.

3 participants