From 413cb8076cceb222fa921555dee73f44955b0407 Mon Sep 17 00:00:00 2001 From: Yujong Lee Date: Sun, 30 Aug 2026 18:55:08 -0700 Subject: [PATCH] fix(router): fail closed on missing named credentials --- litellm/router.py | 1 + litellm/types/router.py | 1 + tests/test_litellm/test_router.py | 39 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/litellm/router.py b/litellm/router.py index f8d69906cac..50841410a23 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -9635,6 +9635,7 @@ class Router: verbose_router_logger.warning( "Credential '%s' not found in credential_list", deployment.litellm_params.litellm_credential_name ) + return None credentials.update(credential_values) # Remove the credential name since we've resolved it credentials.pop("litellm_credential_name", None) diff --git a/litellm/types/router.py b/litellm/types/router.py index ab6c807ba20..1688ff65b30 100644 --- a/litellm/types/router.py +++ b/litellm/types/router.py @@ -241,6 +241,7 @@ class CredentialLiteLLMParams(BaseModel): api_key: str | None = None api_base: str | None = None api_version: str | None = None + project_id: str | None = None ## AZURE OAUTH ## # Without this field, ``get_deployment_credentials_with_provider`` # round-trips ``litellm_params`` through a strict Pydantic dump and diff --git a/tests/test_litellm/test_router.py b/tests/test_litellm/test_router.py index 86ba8aefa28..1b39af44494 100644 --- a/tests/test_litellm/test_router.py +++ b/tests/test_litellm/test_router.py @@ -4539,6 +4539,45 @@ def test_get_deployment_credentials_with_provider_resolves_credential_name(): litellm.credential_list = [] +def test_get_deployment_credentials_with_provider_fails_closed_for_missing_named_credential(): + router = litellm.Router( + model_list=[ + { + "model_name": "embedding-model", + "litellm_params": { + "model": "azure/text-embedding-3-small", + "litellm_credential_name": "deleted-credential", + }, + } + ] + ) + + with patch.object(litellm, "credential_list", []): + credentials = router.get_deployment_credentials_with_provider(model_id="embedding-model") + + assert credentials is None + + +def test_get_deployment_credentials_with_provider_preserves_project_id(): + router = litellm.Router( + model_list=[ + { + "model_name": "embedding-model", + "litellm_params": { + "model": "watsonx/ibm/slate-125m-english-rtrvr", + "api_key": "test-key", + "project_id": "embedding-project", + }, + } + ] + ) + + credentials = router.get_deployment_credentials_with_provider(model_id="embedding-model") + + assert credentials is not None + assert credentials["project_id"] == "embedding-project" + + def test_get_deployment_credentials_with_provider_bedrock_batch_fields(): """ Test that get_deployment_credentials_with_provider returns the deployment's