Skip to content

fix(ch06): guard against IndexError on empty LLM choices list#1221

Open
qizwiz wants to merge 2 commits into
microsoft:mainfrom
qizwiz:fix/guard-empty-llm-choices
Open

fix(ch06): guard against IndexError on empty LLM choices list#1221
qizwiz wants to merge 2 commits into
microsoft:mainfrom
qizwiz:fix/guard-empty-llm-choices

Conversation

@qizwiz
Copy link
Copy Markdown

@qizwiz qizwiz commented May 17, 2026

Problem

Nine example scripts in chapter 06 call choices[0].message.content without checking whether the API returned any choices. This raises a bare IndexError when:

  • the LLM applies a content-policy filter and returns choices=[]
  • a token limit is hit before the first choice is generated
  • the API returns a non-standard error response body

These are tutorial scripts that learners copy and run — an IndexError here is confusing and makes the example look broken.

Changes

File Fix
aoai-app.py if completion.choices: before printing
aoai-history-bot.py same
aoai-study-buddy.py same
oai-app.py same
oai-history-bot.py same
oai-study-buddy.py same
githubmodels-app.py if response.choices: before printing
aoai-app-recipe.py guard both choices accesses; skip dependent shopping-list call when first response is empty
oai-app-recipe.py same

All changes are minimal defensive checks — no logic changes for successful API responses.


Found by pact static analysis — llm_response_unguarded mode.

Nine example scripts in chapter 06 access choices[0] without checking
whether the API returned any choices. Content-policy filters, token
limits, and non-standard responses can all return choices=[].

- aoai-app.py, aoai-history-bot.py, aoai-study-buddy.py: wrap print in `if completion.choices`
- oai-app.py, oai-history-bot.py, oai-study-buddy.py: same
- githubmodels-app.py: wrap print in `if response.choices`
- aoai-app-recipe.py, oai-app-recipe.py: guard both choices accesses and
  skip the dependent shopping-list call when first response is empty
@github-actions
Copy link
Copy Markdown
Contributor

👋 Thanks for contributing @qizwiz! We will review the pull request and get back to you soon.

…content-filter)

Gemini 2.5 Flash returns HTTP 200 with choices[0].message=None when content
is filtered, causing AttributeError even when choices is non-empty. Extends
all 9 app guards to also check `message is not None` / `message is None`.
@qizwiz
Copy link
Copy Markdown
Author

qizwiz commented May 17, 2026

Update: extended guards to cover Gemini content-filter crash path

Testing against live providers found that Gemini 2.5 Flash returns HTTP 200 with choices[0].message = None (not an empty choices list) when content is filtered — finish_reason: PROHIBITED_CONTENT. The previous guards if completion.choices: only prevent IndexError on empty lists; AttributeError: 'NoneType' object has no attribute 'content' still occurs when message itself is None.

Pushed follow-up commit (05bd9ac) extending all 9 app files to the comprehensive guard:

if completion.choices and completion.choices[0].message is not None:
    print(completion.choices[0].message.content)

This covers both crash vectors in a single check.

@qizwiz
Copy link
Copy Markdown
Author

qizwiz commented May 26, 2026

Quick status summary for reviewers:

This PR guards against two distinct crash paths in the chapter 06 tutorial scripts:

  1. Empty choices (IndexError) — when content policy filters the response, choices=[]. Fixed with if completion.choices: before indexing.
  2. None message (AttributeError) — Gemini 2.5 Flash returns HTTP 200 with choices[0].message = None when finish_reason: PROHIBITED_CONTENT. Fixed with an additional and completion.choices[0].message is not None check.

Both are real failure modes learners will hit when running these examples against live APIs. The guards are minimal and don't change the tutorial logic — they just print a friendly message instead of crashing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants