fix(router): pass container create/list through when model names no deployment

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-09-01 23:39:42 +00:00
parent 4a68abfd49
commit acc65b27d2
3 changed files with 38 additions and 3 deletions

View file

@ -6590,8 +6590,9 @@ class Router:
upstream value, and route through ``_ageneric_api_call_with_fallbacks`` so
deployment credentials (e.g. regional ``api_base`` for Azure) match
:meth:`_init_responses_api_endpoints`. Create/list calls carry no container ID, so
they route through the deployment named by ``model`` when the caller passes one.
Otherwise call the handler directly with global provider credentials.
they route through the deployment named by ``model`` when the caller passes one,
falling back to the direct call when no deployment matches. Otherwise call the
handler directly with global provider credentials.
"""
if custom_llm_provider and "custom_llm_provider" not in kwargs:
kwargs["custom_llm_provider"] = custom_llm_provider
@ -6627,6 +6628,7 @@ class Router:
if isinstance(requested_model, str) and requested_model.strip():
return await self._ageneric_api_call_with_fallbacks(
original_function=original_function,
passthrough_on_no_deployment=True,
**kwargs,
)

View file

@ -1383,6 +1383,39 @@ async def test_init_containers_api_endpoints_create_without_model_calls_directly
mock_original_function.assert_called_once_with(custom_llm_provider="openai", name="Test Container", model=None)
@pytest.mark.asyncio
async def test_init_containers_api_endpoints_create_with_unknown_model_passes_through(monkeypatch):
"""
A ``model`` that names no configured deployment must not turn into a 400. The call
falls through to the handler with the caller's model and no injected deployment
credentials, matching the behaviour before model-based routing existed.
"""
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
router = Router(
model_list=[
{
"model_name": "gpt-5.4",
"litellm_params": {"model": "openai/gpt-5.4", "api_key": "sk-model-list-key"},
}
]
)
mock_original_function = AsyncMock(return_value={"id": "cntr_test"})
await router._init_containers_api_endpoints(
original_function=mock_original_function,
custom_llm_provider="openai",
name="Test Container",
model="does-not-exist",
)
mock_original_function.assert_called_once()
call_kw = mock_original_function.call_args.kwargs
assert call_kw["model"] == "does-not-exist"
assert call_kw["name"] == "Test Container"
assert "api_key" not in call_kw
assert "api_base" not in call_kw
def test_router_model_group_encrypted_content_affinity_callback_registration():
from litellm.router_utils.pre_call_checks.deployment_affinity_check import (
DeploymentAffinityCheck,

View file

@ -172,7 +172,7 @@ class TestContainerAPI:
async def _resolve_upstream():
return upstream_response
with patch.object( # test-quality-ok: create_container does not forward a client, so the handler is the only seam
with patch.object( # test-quality-ok: create_container exposes no client seam, only the handler
base_llm_http_handler,
"container_create_handler",
side_effect=lambda **kwargs: _resolve_upstream() if kwargs["_is_async"] else upstream_response,