Skip to content

Fix crash when scorer LLM response is blocked by content filter#2072

Open
hannahwestra25 wants to merge 7 commits into
microsoft:mainfrom
hannahwestra25:hannahwestra25/fix-scorer-content-filter-crash
Open

Fix crash when scorer LLM response is blocked by content filter#2072
hannahwestra25 wants to merge 7 commits into
microsoft:mainfrom
hannahwestra25:hannahwestra25/fix-scorer-content-filter-crash

Conversation

@hannahwestra25

Copy link
Copy Markdown
Contributor

When the scorer's own LLM call is blocked by Azure content filtering (e.g., because it's grading harmful content), the response contains only an error piece with no text piece. The next() generator in _score_value_with_llm_async raises StopIteration, which becomes a RuntimeError inside the async coroutine.

This adds an explicit check before the next() call and raises a descriptive BadRequestException suggesting the user configure a scorer endpoint without content filtering.

hannahwestra25 and others added 3 commits June 23, 2026 21:07
When the scorer's own LLM call is blocked by Azure content filtering,
the response contains only an error piece with no text piece. The
next() call in _score_value_with_llm_async raises StopIteration, which
becomes a RuntimeError inside the async coroutine.

Add an explicit check for all-blocked response pieces before the next()
call and raise a descriptive BadRequestException instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread pyrit/score/scorer.py
# Require every piece to be blocked (all) rather than any: a partially blocked
# response may still carry a usable text piece, so we only bail out when there
# is no salvageable content to parse.
if all(piece.is_blocked() for piece in response[0].message_pieces):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a piece is blocked, every piece is marked blocked. The piece's converted_value has the error JSON. There is partial content in the metadata, but no non-blocked text piece.

So this should be updated because it will never get partial content.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, you're right. A content-filter block always comes back as a single fully-blocked error piece (partial content lives in prompt_metadata, not a separate text piece), so the old comment's salvageable text piece reasoning was wrong. Fixed the comment in 0aa44b9 to just say a block yields a single error piece with no parseable text. The all() check is functionally equivalent to checking the first piece here; kept it as a harmless defensive check rather than changing behavior.

A content-filter block always yields a single fully-blocked error piece, so the previous comment's claim about a salvageable text piece was inaccurate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

4 participants