Skip to content

fix: guard against empty choices and message=None in OpenAI responses#1138

Open
qizwiz wants to merge 1 commit into
PDFMathTranslate:mainfrom
qizwiz:fix/guard-unguarded-llm-choices
Open

fix: guard against empty choices and message=None in OpenAI responses#1138
qizwiz wants to merge 1 commit into
PDFMathTranslate:mainfrom
qizwiz:fix/guard-unguarded-llm-choices

Conversation

@qizwiz
Copy link
Copy Markdown

@qizwiz qizwiz commented May 17, 2026

Problem

OpenAI-compatible APIs can fail silently in two ways:

  1. Empty choices list (IndexError): response.choices is [] when the API returns no completions
  2. message=None (AttributeError): response.choices[0].message is None when content is filtered (e.g., Gemini returns HTTP 200 with PROHIBITED_CONTENT, message=None)

Both paths cause unhandled runtime exceptions during translation, aborting the entire translation job.

Affected code

Three Translator subclasses in pdf2zh/translator.py have unguarded accesses (4 sites total — lines 549, 628, 631, 1198 in the original).

Fix

Adds the standard two-condition guard before each bare choices[0].message.content access:

if not response.choices or response.choices[0].message is None:
    raise ValueError("LLM returned empty or filtered response")

This converts silent crashes into explicit, actionable errors with a clear message.

8 lines added, 0 deleted.

Verification

Detected by pact static analysis (llm_response_unguarded rule). Confirmed: Gemini 2.5 Flash returns HTTP 200 with choices[0].message=None on prohibited content.

OpenAI-compatible APIs can return empty choices (IndexError) or
choices[0].message=None when content is filtered (HTTP 200, AttributeError).

Adds two-condition guard before bare choices[0].message.content accesses
in 3 Translator subclasses (4 total sites, 3 were unguarded).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.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.

1 participant