diff --git a/litellm/proxy/management_endpoints/team_callback_endpoints.py b/litellm/proxy/management_endpoints/team_callback_endpoints.py index f28db70ef5d..934824dd89f 100644 --- a/litellm/proxy/management_endpoints/team_callback_endpoints.py +++ b/litellm/proxy/management_endpoints/team_callback_endpoints.py @@ -251,20 +251,18 @@ async def disable_team_logging( }, } + except HTTPException: + # Legitimate 4xx (e.g. 403 from the access guard, 404 for an + # unknown team). Re-raise without the error-level log noise that + # the catch-all branch below would produce. + raise + except ProxyException: + raise except Exception as e: verbose_proxy_logger.error( f"litellm.proxy.proxy_server.disable_team_logging(): Exception occurred - {str(e)}" ) verbose_proxy_logger.debug(traceback.format_exc()) - if isinstance(e, HTTPException): - raise ProxyException( - message=getattr(e, "detail", f"Internal Server Error({str(e)})"), - type=ProxyErrorTypes.internal_server_error.value, - param=getattr(e, "param", "None"), - code=getattr(e, "status_code", status.HTTP_500_INTERNAL_SERVER_ERROR), - ) - elif isinstance(e, ProxyException): - raise e raise ProxyException( message="Internal Server Error, " + str(e), type=ProxyErrorTypes.internal_server_error.value, @@ -349,6 +347,13 @@ async def get_team_callbacks( }, } + except HTTPException: + # Legitimate 4xx (e.g. 403 from the access guard) — re-raise + # without the error-level log noise that the catch-all below + # would produce. + raise + except ProxyException: + raise except Exception as e: verbose_proxy_logger.error( "litellm.proxy.proxy_server.get_team_callbacks(): Exception occurred - {}".format( diff --git a/tests/test_litellm/proxy/management_endpoints/test_team_callback_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_team_callback_endpoints.py index 745c0583bbd..e26820ea9cd 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_team_callback_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_team_callback_endpoints.py @@ -108,18 +108,16 @@ async def test_add_team_callbacks_rejects_unauthorized_caller( async def test_disable_team_logging_rejects_unauthorized_caller( patched_prisma, unauthorized_caller ): - # The endpoint catches HTTPException and re-wraps it as ProxyException - # with the original status code preserved. - from litellm.proxy._types import ProxyException - - with pytest.raises((HTTPException, ProxyException)) as exc: + # The HTTPException from the access guard now propagates directly + # — the catch-all that previously re-wrapped (and logged at error + # level) was narrowed so legitimate 4xx don't pollute alerting. + with pytest.raises(HTTPException) as exc: await disable_team_logging( http_request=Mock(spec=Request), team_id="team-victim", user_api_key_dict=unauthorized_caller, ) - code = getattr(exc.value, "status_code", None) or getattr(exc.value, "code", None) - assert int(code) == 403 + assert exc.value.status_code == 403 patched_prisma.db.litellm_teamtable.update.assert_not_called() @@ -127,20 +125,13 @@ async def test_disable_team_logging_rejects_unauthorized_caller( async def test_get_team_callbacks_rejects_unauthorized_caller( patched_prisma, unauthorized_caller ): - # The endpoint catches generic Exception and re-wraps as ProxyException; - # an HTTPException raised by the access guard surfaces as a 403 - # ProxyException — both shapes are acceptable failure modes, what - # matters is that the caller does NOT receive the team's callback data. - from litellm.proxy._types import ProxyException - - with pytest.raises((HTTPException, ProxyException)) as exc: + with pytest.raises(HTTPException) as exc: await get_team_callbacks( http_request=Mock(spec=Request), team_id="team-victim", user_api_key_dict=unauthorized_caller, ) - code = getattr(exc.value, "status_code", None) or getattr(exc.value, "code", None) - assert int(code) == 403 + assert exc.value.status_code == 403 @pytest.mark.asyncio