This commit is contained in:
wasim 2026-08-27 17:04:34 -05:00 committed by GitHub
commit 6d9c2e4c87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 0 deletions

View file

@ -14,6 +14,7 @@ from datetime import datetime
from re import Pattern
from typing import TYPE_CHECKING, Any, Final, Literal, Optional, TypedDict, cast
import openai
import yaml
from fastapi import HTTPException
@ -2056,6 +2057,13 @@ class ContentFilterGuardrail(CustomGuardrail):
except HTTPException:
status = "guardrail_intervened"
raise
except openai.OpenAIError as e:
# Upstream provider/stream error propagating through the iterator.
# The guardrail never evaluated content, so it must not be recorded
# as a guardrail failure. "not_run" is the canonical status here.
status = "not_run"
exception_str = str(e)
raise
except Exception as e:
status = "guardrail_failed_to_respond"
exception_str = str(e)

View file

@ -0,0 +1,42 @@
import openai
from unittest.mock import MagicMock
import pytest
from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import (
ContentFilterGuardrail,
)
from litellm.types.guardrails import GuardrailEventHooks
@pytest.mark.asyncio
async def test_streaming_hook_upstream_error_is_not_run():
"""
When the upstream stream raises a provider error (openai.OpenAIError
subclass), the content filter never evaluates content. The error must
propagate unchanged and be logged as "not_run", not as a guardrail
failure. Regression test for issue #31004.
"""
guardrail = ContentFilterGuardrail(
guardrail_name="test-streaming-upstream-error",
patterns=[],
event_hook=GuardrailEventHooks.during_call,
)
async def mock_stream():
raise openai.APIError("Provider returned error", request=MagicMock(), body=None)
yield # pragma: no cover - makes this an async generator
user_api_key_dict = MagicMock()
request_data: dict = {}
with pytest.raises(openai.APIError):
async for _ in guardrail.async_post_call_streaming_iterator_hook(
user_api_key_dict=user_api_key_dict,
response=mock_stream(),
request_data=request_data,
):
pass
info = request_data["metadata"]["standard_logging_guardrail_information"][0]
assert info["guardrail_status"] == "not_run"