Skip to content

fix(openai): guard against choices=None in OpenAI integration#6216

Open
cla7aye15I4nd wants to merge 2 commits intogetsentry:masterfrom
cla7aye15I4nd:fix/openai-choices-none
Open

fix(openai): guard against choices=None in OpenAI integration#6216
cla7aye15I4nd wants to merge 2 commits intogetsentry:masterfrom
cla7aye15I4nd:fix/openai-choices-none

Conversation

@cla7aye15I4nd
Copy link
Copy Markdown

Summary

Some providers (e.g. OpenRouter) can return choices=None on upstream error responses. The current code checks hasattr(response, "choices") before iterating, but hasattr returns True even when the attribute value is None, causing:

TypeError: 'NoneType' object is not iterable
  File "sentry_sdk/integrations/openai.py", line 164, in _calculate_token_usage
    for choice in response.choices:

This crash happens inside Sentry's patched create() wrapper before the calling code ever receives the response, making it impossible to handle on the caller side without catching a bare TypeError.

Fix

Add an explicit response.choices is not None guard alongside the existing hasattr check at both affected locations.

Reproduction

Use the OpenAI SDK client pointed at OpenRouter (base_url="https://openrouter.ai/api/v1"). When an upstream provider fails, OpenRouter returns a response with choices=null, which triggers this crash in Sentry's telemetry hook.

Some providers (e.g. OpenRouter) can return choices=None on upstream
error responses. hasattr(response, 'choices') returns True even when
the attribute is None, causing a TypeError when iterating.

Add an explicit None check before iterating response.choices.
@cla7aye15I4nd cla7aye15I4nd requested a review from a team as a code owner May 6, 2026 22:55
Comment thread sentry_sdk/integrations/openai.py
When a streaming chunk has choices=None, the existing hasattr check passes
but the subsequent iteration raises TypeError. Inside capture_internal_exceptions()
this is silently suppressed, causing the usage capture on the next line to be
skipped — leaving token usage and response text missing from the Sentry span.

Add explicit None checks in both the sync and async streaming iterators.
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