fix(router): restore BYOK key injection for vector store endpoints with team-scoped deployments - #25746
Conversation
…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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR fixes BYOK credential injection for vector store endpoints (e.g. Confidence Score: 4/5Fix 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
|
| 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]
Reviews (4): Last reviewed commit: "Merge branch 'litellm_internal_staging' ..." | Re-trigger Greptile
| 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") |
There was a problem hiding this comment.
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 Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
… litellm_vector-store-team-byok-model-none
Low: Minor routing logic extension for team-scoped BYOKThis PR modifies Status: 0 open Posted by Veria AI · 2026-04-24T00:33:57.983Z |
Low: No security issues foundThis PR widens the Status: 0 open Posted by Veria AI · 2026-04-24T00:36:03.271Z |
…m-byok-model-none
Low: Narrow change to team model resolutionThis PR modifies Status: 0 open Posted by Veria AI · 2026-04-24T00:42:47.712Z |
|
| 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
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- 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
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 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 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
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- 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
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 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.
…am-byok-model-none fix(router): restore BYOK key injection for vector store endpoints with team-scoped deployments
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
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays 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)
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.