Skip to content

Fix/team public model name overwrite - #29001

Merged
yuneng-berri merged 1 commit into
BerriAI:litellm_yj_june4from
tushar8408:fix/team-public-model-name-overwrite
Jun 5, 2026
Merged

Fix/team public model name overwrite#29001
yuneng-berri merged 1 commit into
BerriAI:litellm_yj_june4from
tushar8408:fix/team-public-model-name-overwrite

Conversation

@tushar8408

@tushar8408 tushar8408 commented May 27, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Linear ticket

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

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

@greptile-apps

greptile-apps Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where a dashboard PATCH on a team-scoped model would overwrite team_public_model_name with the internal UUID-based model_name because the dashboard re-sends the internal name on every save.

  • Core fix: _get_public_model_name now checks patch_data.model_info.team_public_model_name first, and only falls through to patch_data.model_name when it genuinely differs from db_model.model_name, preventing no-op dashboard saves from triggering spurious renames.
  • Tests: Seven new unit and end-to-end tests cover each branch of the new precedence logic, including the regression scenario from issue [Bug]: Team-scoped model edit can overwrite public model name with internal model name #28382.

Confidence Score: 4/5

The change is narrowly scoped to a single helper function and is well-covered by new tests; the fix correctly restores the intended precedence for public model name resolution without touching the broader request path.

The logic change is straightforward and the new test suite exercises every branch of the updated function. One end-to-end test assertion is looser than it should be (accepting None for a field that cannot be None), but this does not affect the correctness of the production code itself. The PR description omits the issue reference, but the tests document the regression clearly.

The test file test_model_management_endpoints.py has the overly permissive assertion worth tightening before merge.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/model_management_endpoints.py Adds new precedence rule to _get_public_model_name: explicit patch_data.model_info.team_public_model_name wins over re-sent model_name, and the existing model_name check is now guarded by an inequality comparison against db_model.model_name to prevent dashboard no-op saves from overwriting the public name.
tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py Adds 7 targeted unit/integration tests covering the new precedence logic; one end-to-end test assertion accepts None as a valid model_name return value even though update_db_model always initialises model_name from db_model.model_name, making the assertion weaker than intended.

Comments Outside Diff (1)

  1. litellm/proxy/management_endpoints/model_management_endpoints.py, line 489-517 (link)

    P2 Missing issue link in PR description

    The PR description has no Fixes #… reference, but every test docstring mentions issue #28382. Having the fix disconnected from the issue makes traceability harder and leaves the pre-submission checklist requirement (evidence of resolution) unmet.

    Rule Used: What: Ensure that any PR claiming to fix an issue ... (source)

Reviews (1): Last reviewed commit: "test: end-to-end regression for dashboar..." | Re-trigger Greptile

Comment thread tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py Outdated
@CLAassistant

CLAassistant commented May 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...management_endpoints/model_management_endpoints.py 87.50% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@tushar8408
tushar8408 force-pushed the fix/team-public-model-name-overwrite branch 2 times, most recently from 45c2094 to b280630 Compare June 2, 2026 20:41
Comment thread litellm/proxy/proxy_server.py
@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

@tushar8408
tushar8408 force-pushed the fix/team-public-model-name-overwrite branch from b280630 to 241e852 Compare June 2, 2026 23:26
Team-scoped ("Team-BYOK") models store an internal routing key
model_name_{team_id}_{uuid} in the model_name column and the user-facing
name in model_info.team_public_model_name. The internal name leaked into
/v1, /v2, and /model/info responses; the dashboard bound its edit form to
it, so any non-rename save (e.g. a TPM tweak) PATCHed the internal name
back. The update path then treated it as a rename, overwriting
team_public_model_name and rewriting the team's models[] ACL with the
mangled string -- breaking team key calls with team_model_access_denied.

Two-layer fix:

- Read path (root cause): add _translate_model_name_for_response and apply
  it in model_info_v2 and _get_proxy_model_info so /v1, /v2, and
  /model/info surface the public name for team-scoped rows. The DB column
  and router index keep the internal name as the routing key; this is a
  presentation-layer swap on a shallow copy (never mutates input).

- Write path (defense in depth): harden _get_public_model_name so a value
  matching the internal shape, or a no-op against the current DB column,
  is never treated as a rename -- for both the top-level model_name and an
  explicit model_info.team_public_model_name.

Tests: regression for the reported scenario, full branch coverage of
_get_public_model_name, two internal-shape guard cases, an end-to-end
PATCH through _update_team_model_in_db (asserts the team ACL is untouched),
and four response-translation cases. 60 passed (model management),
181 passed (proxy server).
@tushar8408
tushar8408 force-pushed the fix/team-public-model-name-overwrite branch from 241e852 to fcdfaf1 Compare June 3, 2026 16:24
@yuneng-berri
yuneng-berri changed the base branch from litellm_internal_staging to litellm_yj_june4 June 5, 2026 01:44
@yuneng-berri
yuneng-berri merged commit fa470a9 into BerriAI:litellm_yj_june4 Jun 5, 2026
45 of 46 checks passed
yuneng-berri added a commit that referenced this pull request Jun 5, 2026
* fix(proxy): stop team model name corruption on edit (#28382) (#29001)

Team-scoped ("Team-BYOK") models store an internal routing key
model_name_{team_id}_{uuid} in the model_name column and the user-facing
name in model_info.team_public_model_name. The internal name leaked into
/v1, /v2, and /model/info responses; the dashboard bound its edit form to
it, so any non-rename save (e.g. a TPM tweak) PATCHed the internal name
back. The update path then treated it as a rename, overwriting
team_public_model_name and rewriting the team's models[] ACL with the
mangled string -- breaking team key calls with team_model_access_denied.

Two-layer fix:

- Read path (root cause): add _translate_model_name_for_response and apply
  it in model_info_v2 and _get_proxy_model_info so /v1, /v2, and
  /model/info surface the public name for team-scoped rows. The DB column
  and router index keep the internal name as the routing key; this is a
  presentation-layer swap on a shallow copy (never mutates input).

- Write path (defense in depth): harden _get_public_model_name so a value
  matching the internal shape, or a no-op against the current DB column,
  is never treated as a rename -- for both the top-level model_name and an
  explicit model_info.team_public_model_name.

Tests: regression for the reported scenario, full branch coverage of
_get_public_model_name, two internal-shape guard cases, an end-to-end
PATCH through _update_team_model_in_db (asserts the team ACL is untouched),
and four response-translation cases. 60 passed (model management),
181 passed (proxy server).

* fix(ui): key Agent Builder agent selection on model_info.id (#29729)

* fix(ui): key Agent Builder agent selection on model_info.id

Once team-scoped BYOK models can share a public name (the backend now
returns the public name on /model/info instead of the internal routing
key), selecting agents by model_name collides. Key selection, create,
update and delete on the stable model_info.id instead, falling back to
model_name only for config-defined agents that have no id.

* fix(ui): add name-match fallback to post-create agent selection

If the just-created agent's id is not yet present in the re-fetched
list, try matching by name before falling back to the first agent.
Addresses greptile review on #29729.

---------

Co-authored-by: tushar8408 <32977767+tushar8408@users.noreply.github.com>
yuneng-berri added a commit that referenced this pull request Jun 14, 2026
* fix(proxy): stop team model name corruption on edit (#28382) (#29001)

Team-scoped ("Team-BYOK") models store an internal routing key
model_name_{team_id}_{uuid} in the model_name column and the user-facing
name in model_info.team_public_model_name. The internal name leaked into
/v1, /v2, and /model/info responses; the dashboard bound its edit form to
it, so any non-rename save (e.g. a TPM tweak) PATCHed the internal name
back. The update path then treated it as a rename, overwriting
team_public_model_name and rewriting the team's models[] ACL with the
mangled string -- breaking team key calls with team_model_access_denied.

Two-layer fix:

- Read path (root cause): add _translate_model_name_for_response and apply
  it in model_info_v2 and _get_proxy_model_info so /v1, /v2, and
  /model/info surface the public name for team-scoped rows. The DB column
  and router index keep the internal name as the routing key; this is a
  presentation-layer swap on a shallow copy (never mutates input).

- Write path (defense in depth): harden _get_public_model_name so a value
  matching the internal shape, or a no-op against the current DB column,
  is never treated as a rename -- for both the top-level model_name and an
  explicit model_info.team_public_model_name.

Tests: regression for the reported scenario, full branch coverage of
_get_public_model_name, two internal-shape guard cases, an end-to-end
PATCH through _update_team_model_in_db (asserts the team ACL is untouched),
and four response-translation cases. 60 passed (model management),
181 passed (proxy server).

* fix(ui): key Agent Builder agent selection on model_info.id (#29729)

* fix(ui): key Agent Builder agent selection on model_info.id

Once team-scoped BYOK models can share a public name (the backend now
returns the public name on /model/info instead of the internal routing
key), selecting agents by model_name collides. Key selection, create,
update and delete on the stable model_info.id instead, falling back to
model_name only for config-defined agents that have no id.

* fix(ui): add name-match fallback to post-create agent selection

If the just-created agent's id is not yet present in the re-fetched
list, try matching by name before falling back to the first agent.
Addresses greptile review on #29729.

---------

Co-authored-by: tushar8408 <32977767+tushar8408@users.noreply.github.com>
(cherry picked from commit 56aa55b)
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…AI#29731)

* fix(proxy): stop team model name corruption on edit (BerriAI#28382) (BerriAI#29001)

Team-scoped ("Team-BYOK") models store an internal routing key
model_name_{team_id}_{uuid} in the model_name column and the user-facing
name in model_info.team_public_model_name. The internal name leaked into
/v1, /v2, and /model/info responses; the dashboard bound its edit form to
it, so any non-rename save (e.g. a TPM tweak) PATCHed the internal name
back. The update path then treated it as a rename, overwriting
team_public_model_name and rewriting the team's models[] ACL with the
mangled string -- breaking team key calls with team_model_access_denied.

Two-layer fix:

- Read path (root cause): add _translate_model_name_for_response and apply
  it in model_info_v2 and _get_proxy_model_info so /v1, /v2, and
  /model/info surface the public name for team-scoped rows. The DB column
  and router index keep the internal name as the routing key; this is a
  presentation-layer swap on a shallow copy (never mutates input).

- Write path (defense in depth): harden _get_public_model_name so a value
  matching the internal shape, or a no-op against the current DB column,
  is never treated as a rename -- for both the top-level model_name and an
  explicit model_info.team_public_model_name.

Tests: regression for the reported scenario, full branch coverage of
_get_public_model_name, two internal-shape guard cases, an end-to-end
PATCH through _update_team_model_in_db (asserts the team ACL is untouched),
and four response-translation cases. 60 passed (model management),
181 passed (proxy server).

* fix(ui): key Agent Builder agent selection on model_info.id (BerriAI#29729)

* fix(ui): key Agent Builder agent selection on model_info.id

Once team-scoped BYOK models can share a public name (the backend now
returns the public name on /model/info instead of the internal routing
key), selecting agents by model_name collides. Key selection, create,
update and delete on the stable model_info.id instead, falling back to
model_name only for config-defined agents that have no id.

* fix(ui): add name-match fallback to post-create agent selection

If the just-created agent's id is not yet present in the re-fetched
list, try matching by name before falling back to the first agent.
Addresses greptile review on BerriAI#29729.

---------

Co-authored-by: tushar8408 <32977767+tushar8408@users.noreply.github.com>
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