Skip to content

OpenAI integration raises TypeError: 'NoneType' object is not iterable into user code when response.output is None #7222

Description

@FromCSUZhou

How do you use Sentry?

Sentry Saas (sentry.io)

Version

2.68.0 (also reproduces on 2.35.1 and 2.40.0)

Steps to Reproduce

The OpenAI integration raises out of the instrumented create() call when a response object has a None collection where the integration expects an iterable. The exception is not contained by the SDK, so it surfaces as an application error and replaces whatever the API actually returned.

This is reachable in practice through OpenAI-compatible gateways. When a gateway has already flushed 200 OK (for example after sending keep-alive padding while it buffers a large request) and only then learns the upstream call failed, it can no longer change the status code, so it reports the failure in the body:

{"error": {"message": "... At least one of the image dimensions exceed max allowed size: 8000 pixels", "code": 400}}

The openai client parses that into a model object with no output / choices populated, and instrumenting it raises.

Minimal reproduction, no network needed:

from unittest import mock

import sentry_sdk
from openai import OpenAI
from openai.types.responses import Response
from sentry_sdk.integrations.openai import OpenAIIntegration

sentry_sdk.init(
    dsn="https://public@o1.ingest.sentry.io/1",
    traces_sample_rate=1.0,
    integrations=[OpenAIIntegration()],
    transport=lambda event: None,
)

# What the client parses out of a 200 response that only carries an error
gateway_error = Response.construct(
    error={"message": "upstream failed", "code": 400},
    output=None,
)

client = OpenAI(api_key="z")
client.responses._post = mock.Mock(return_value=gateway_error)

with sentry_sdk.start_transaction(name="tx"):
    response = client.responses.create(model="gpt-4o", input="hello")
    print(response.error)

Expected Result

create() returns the response object, and the application can read response.error to see what actually went wrong. Instrumentation problems stay inside the SDK.

Actual Result

  File "sentry_sdk/integrations/openai.py", line 1532, in _new_sync_responses_create
    _set_responses_api_output_data(
  File "sentry_sdk/integrations/openai.py", line 1275, in _set_responses_api_output_data
    _set_common_output_data(
  File "sentry_sdk/integrations/openai.py", line 746, in _set_common_output_data
    for output in response.output:
                  ^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not iterable

The application never sees the real error message, so any retry/fallback logic keyed on it stops working.

There appear to be two separate causes:

  1. response.output is not checked for None. response.choices was given an is not None check after OpenAI integration fails when response has no messages in choices. #5071, but the Responses API branch still does a bare hasattr(response, "output") in _set_common_output_data and _calculate_responses_token_usage.

  2. The non-streaming paths lost their capture_internal_exceptions() wrapper. Before OpenAI integration update #4612 the whole response-handling block ran inside with capture_internal_exceptions():. The restructuring into _set_*_input_data / _set_*_output_data moved that code out from under the wrapper, so any error there now propagates into user code. The streaming iterators kept their protection; the non-streaming paths did not. This is why <2.34 is unaffected.

The second point is the more general one — with it fixed, this class of bug degrades to a missing span attribute rather than an application crash, which matches the SDK contract in CONTRIBUTING.md ("Users do not expect their application to crash").

I have a patch with tests for both points and am happy to open a PR if this looks like the right direction.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions