From 23a7e1dc29212013073710131c367d5c194d5f1c Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Thu, 8 Oct 2026 23:02:14 -0700 Subject: [PATCH] fix(client): percent-encode the credential name when updating its display name A name with ? or # was cut short in the URL, so the PATCH landed on a different credential or 404'd. --- litellm/proxy/client/credentials.py | 3 ++- tests/unit/proxy/client/test_credentials.py | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/client/credentials.py b/litellm/proxy/client/credentials.py index 43dd147da21..ebcd79457a6 100644 --- a/litellm/proxy/client/credentials.py +++ b/litellm/proxy/client/credentials.py @@ -1,5 +1,6 @@ from collections.abc import Mapping from typing import Any, Final +from urllib.parse import quote import requests @@ -159,7 +160,7 @@ class CredentialsManagementClient: display_name: str | None, return_request: bool = False, ) -> Mapping[str, object] | requests.Request: - url: Final = f"{self._base_url}/credentials/{credential_name}" + url: Final = f"{self._base_url}/credentials/{quote(credential_name, safe='')}" data: Final[Mapping[str, object]] = {"display_name": display_name, "credential_info": {}} request: Final = requests.Request("PATCH", url, headers=self._get_headers(), json=data) diff --git a/tests/unit/proxy/client/test_credentials.py b/tests/unit/proxy/client/test_credentials.py index bedd8d35ee1..9de990da487 100644 --- a/tests/unit/proxy/client/test_credentials.py +++ b/tests/unit/proxy/client/test_credentials.py @@ -148,6 +148,13 @@ def test_update_display_name_request(client, base_url, api_key, display_name): assert request.json == {"display_name": display_name, "credential_info": {}} +@pytest.mark.parametrize(("credential_name", "path"), [("team?prod", "team%3Fprod"), ("a/b#c", "a%2Fb%23c")]) +def test_update_display_name_targets_the_whole_credential_name(client, base_url, credential_name, path): + request = client.update_display_name(credential_name, "Label", return_request=True) + + assert request.prepare().url == f"{base_url}/credentials/{path}" + + @responses.activate def test_create_mock_response(client): """Test create with a mocked successful response"""