Skip to content

fix: raise ContentFilterFinishReasonError on refusal responses#2847

Open
danylokv-lang wants to merge 1 commit intoopenai:mainfrom
danylokv-lang:fix/refusal-content-filter-error
Open

fix: raise ContentFilterFinishReasonError on refusal responses#2847
danylokv-lang wants to merge 1 commit intoopenai:mainfrom
danylokv-lang:fix/refusal-content-filter-error

Conversation

@danylokv-lang
Copy link

@danylokv-lang danylokv-lang commented Feb 6, 2026

Summary

Fixes parsing error where refusal responses caused a confusing pydantic_core.ValidationError instead of a proper SDK exception.

Problem

When content moderation is triggered, the model returns a plain-text refusal like "I'm sorry, but I cannot assist with that request." instead of valid JSON. This refusal text was passed directly to Pydantic validation:

for item in output.content:
    if item.type != "output_text":
        content_list.append(item)
        continue
    # Refusal text reaches here and fails JSON parsing!
    parsed = parse_text(item.text, text_format=text_format)

Since refusal text is not valid JSON, users received a low-level pydantic_core.ValidationError with no indication that the issue was content moderation.

Solution

Added a guard to detect refusal content before attempting Pydantic validation:

for item in output.content:
    if item.type == "refusal":
        from ..._exceptions import ContentFilterFinishReasonError
        raise ContentFilterFinishReasonError() 
    if item.type != "output_text":
        content_list.append(item)
        continue

This is consistent with how refusals are handled in _completions.py (line 102).

Changes

_responses.py: Added refusal detection that raises ContentFilterFinishReasonError

Test Plan

✅ Static analysis passes (no errors)
✅ Logic now surfaces moderation-triggered responses as ContentFilterFinishReasonError
✅ Consistent with chat completions refusal handling
Fixes #2834

When responses.parse() receives a refusal response from the model
(e.g., due to content moderation), it now raises ContentFilterFinishReasonError
instead of letting the refusal text pass through to Pydantic validation,
which would result in a confusing pydantic_core.ValidationError.

This makes the behavior consistent with chat completions parsing,
which already handles refusals properly.

Fixes openai#2834
@danylokv-lang danylokv-lang requested a review from a team as a code owner February 6, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Json parsing error with content moderation

1 participant