Skip to content

fix: handle null response.output in parse_response#3441

Open
C1-BA-B1-F3 wants to merge 2 commits into
openai:mainfrom
C1-BA-B1-F3:fix/parse-response-null-output
Open

fix: handle null response.output in parse_response#3441
C1-BA-B1-F3 wants to merge 2 commits into
openai:mainfrom
C1-BA-B1-F3:fix/parse-response-null-output

Conversation

@C1-BA-B1-F3

Copy link
Copy Markdown

Summary

parse_response() in src/openai/lib/_parsing/_responses.py iterates response.output without checking for None. The chatgpt.com Codex backend (https://chatgpt.com/backend-api/codex) sometimes sends response.output: null in the consolidated response.completed event — even when valid response.output_item.done events were streamed earlier in the same response. The SDK then raises TypeError: 'NoneType' object is not iterable inside the stream accumulator, killing the entire stream before the consumer can read the deltas.

Fix

One-line defensive iteration in parse_response:

-    for output in response.output:
+    for output in (response.output or []):

With this patch the stream completes, get_final_response() returns a Response with output=[], and consumers that already track output_item.done events can backfill the response from their own collected items. No regression on responses that legitimately have output: list.

Tests

Added tests/lib/test_parsing_responses.py with three tests:

  • test_parse_response_with_none_output — verifies null output doesn't crash and returns empty output list
  • test_parse_response_with_empty_list_output — verifies empty list still works
  • test_parse_response_with_message_output — verifies normal output items still parse correctly

Fixes #3325

When a backend sends 'response.output: null' in a response.completed
event (e.g., chatgpt.com Codex backend), parse_response would crash
with TypeError: 'NoneType' object is not iterable.

This one-line fix coerces None to an empty list, allowing the stream
to complete gracefully. Consumers that track output_item.done events
can still backfill from their collected items.

Fixes openai#3325
@C1-BA-B1-F3 C1-BA-B1-F3 requested a review from a team as a code owner June 25, 2026 19:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d91d0d75c2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

output_list: List[ParsedResponseOutputItem[TextFormatT]] = []

for output in response.output:
for output in (response.output or []):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve streamed output for null completed responses

When this runs from ResponseStreamState.accumulate_event() for a response.completed event, event.response.output == None is now converted to an empty final ParsedResponse.output even though the stream state may already contain items accumulated from prior response.output_item.added / text delta events. In that null-output backend scenario, consumers of response.completed.response, get_final_response().output, or get_final_response().output_text silently get an empty response instead of the text/tool calls they just streamed, so the stream no longer crashes but still drops the completed result.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for raising this! You're correct that a null in was overwriting the accumulated stream content, resulting in empty final responses.

The fix preserves accumulated items from prior / text delta events when is null, so consumers get the complete streamed result rather than an empty response. The null output case now only applies when there's genuinely nothing streamed.

Happy to adjust the approach if you prefer a different strategy for handling this edge case!

…ull output

When response.completed arrives with null output, items accumulated from prior streaming events are now preserved by reconstructing the response with the snapshot output.
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.

parse_response crashes with TypeError when response.output is null in response.completed event (chatgpt.com Codex backend)

1 participant