From e4e1eb9939264b752722a1bbb48864ca61368e02 Mon Sep 17 00:00:00 2001 From: Mrinal Chanshetty Date: Sat, 10 Oct 2026 12:53:07 -0700 Subject: [PATCH] test(batches): pin that a pre-call ownership denial stops every batch create branch LIT-4797 noted an endpoint-level check missed the load-balanced branch because it dispatches first. The ownership check lives in the pre-call hook, which runs before branch selection, so a 403 there must keep both the load-balanced and unified-file branches from reaching the router --- .../proxy/batches_endpoints/test_endpoints.py | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/unit/proxy/batches_endpoints/test_endpoints.py b/tests/unit/proxy/batches_endpoints/test_endpoints.py index 3469dbee748..aab2074e49f 100644 --- a/tests/unit/proxy/batches_endpoints/test_endpoints.py +++ b/tests/unit/proxy/batches_endpoints/test_endpoints.py @@ -57,7 +57,7 @@ from litellm.types.llms.openai import BatchJobStatus from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo from litellm.types.utils import CredentialItem, LiteLLMBatch, SpecialEnums -from fastapi import Request, Response +from fastapi import HTTPException, Request, Response # --------------------------------------------------------------------------- # # Fixtures: distinguishable credentials per model so a wrong/hardcoded model_id @@ -1164,6 +1164,34 @@ async def test_create__uses_acreate_batch_route_type(harness, openai_env_creds): assert harness.pre_call.call_args.kwargs["route_type"] == "acreate_batch" +@pytest.mark.asyncio +@pytest.mark.parametrize("loadbalancing", [True, False], ids=["load_balanced", "unified_branch"]) +async def test_create__pre_call_ownership_denial_stops_every_dispatch_branch(harness, loadbalancing: bool): + set_body( + harness, + { + "input_file_id": "litellm_proxy_unified_id", + "model": "vertex-model", + "endpoint": "/v1/chat/completions", + "completion_window": "24h", + }, + ) + harness.is_known_model.return_value = True + harness.pre_call.side_effect = HTTPException(status_code=403, detail="does not have access to the file") + + with ( + patch.object(litellm, "enable_loadbalancing_on_batch_endpoints", loadbalancing), + patch.object(endpoints, "is_base64_encoded_unified_file_id", return_value="unified-xyz"), + patch.object(endpoints, "get_models_from_unified_file_id", return_value=["vertex-model"]), + pytest.raises(ProxyException) as exc, + ): + await call_create(harness) + + assert exc.value.code == "403", exc.value + harness.router_acreate.assert_not_called() + harness.litellm_acreate.assert_not_called() + + def install_managed_files_hook(harness: Harness) -> AsyncMock: prisma_client = AsyncMock() managed_files = PROXY_LiteLLMManagedFiles(MagicMock(async_set_cache=AsyncMock()), prisma_client=prisma_client)