diff --git a/litellm/proxy/analytics_endpoints/analytics_endpoints.py b/litellm/proxy/analytics_endpoints/analytics_endpoints.py index 8e6f9922470..d40e6bad8cd 100644 --- a/litellm/proxy/analytics_endpoints/analytics_endpoints.py +++ b/litellm/proxy/analytics_endpoints/analytics_endpoints.py @@ -143,6 +143,15 @@ async def get_prompt_cache_activity( detail={"error": "Please provide start_date and end_date"}, ) + for label, value in (("start_date", start_date), ("end_date", end_date)): + try: + datetime.strptime(value, "%Y-%m-%d") + except ValueError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail={"error": f"{label} must be in YYYY-MM-DD format"}, + ) + from litellm.proxy.proxy_server import prisma_client if prisma_client is None: diff --git a/tests/test_litellm/proxy/analytics_endpoints/test_analytics_endpoints.py b/tests/test_litellm/proxy/analytics_endpoints/test_analytics_endpoints.py index b830563378b..dd282e5bd8d 100644 --- a/tests/test_litellm/proxy/analytics_endpoints/test_analytics_endpoints.py +++ b/tests/test_litellm/proxy/analytics_endpoints/test_analytics_endpoints.py @@ -98,6 +98,20 @@ def test_prompt_cache_activity_requires_dates(client, monkeypatch): assert response.status_code == 400 +def test_prompt_cache_activity_rejects_bad_date_format(client, monkeypatch): + query_raw = AsyncMock(return_value=[]) + _set_prisma(monkeypatch, query_raw) + + response = client.get( + "/global/activity/cache_hits/prompt_caching", + params={"start_date": "07/10/2026", "end_date": "2026-07-18"}, + ) + + assert response.status_code == 400 + assert "start_date must be in YYYY-MM-DD format" in response.text + query_raw.assert_not_awaited() + + def test_prompt_cache_activity_no_prisma(client, monkeypatch): monkeypatch.setattr(proxy_server, "prisma_client", None)