fix: guard against null output in parse_response and output_text property#3404
fix: guard against null output in parse_response and output_text property#3404adhavan18 wants to merge 2 commits into
Conversation
…erty When the Responses API returns `output: null` in a `response.completed` event (observed with the chatgpt.com Codex backend), iterating `response.output` raised `TypeError: 'NoneType' object is not iterable`. A second related case is `output_text` content items whose `text` field is `null`, which caused `parse_response` to pass `None` to structured text parsing and `output_text` to concatenate `None` into the result. Fixes: - `parse_response` in `lib/_parsing/_responses.py`: iterate `response.output or []` so a null list is treated as empty. - Same function: skip structured parsing for `output_text` items where `item.text is None`; set `parsed=None` for those items instead. - `Response.output_text` property in `types/responses/response.py`: iterate `self.output or []` and skip content items with `text is None`. Adds four regression tests covering all three cases. Closes openai#3325, openai#3063
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49ab38b624
ℹ️ 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 []: |
There was a problem hiding this comment.
Preserve streamed output on null completed payloads
In the streamed Responses path, ResponseStreamState.accumulate_event parses event.response on response.completed (src/openai/lib/streaming/responses/_responses.py:359-364) rather than the accumulated snapshot, so when that final completed event has output=None after earlier output item/text delta events, this new fallback turns the final parsed response into output=[]. In that backend case, stream.get_final_response().output_text and the emitted completed event become empty even though the stream already received valid text; the null completed payload should fall back to the accumulated snapshot instead of discarding it.
Useful? React with 👍 / 👎.
Fixes #3325 and #3063.
Problem
Two crashes in the Responses API when the server returns unexpected null values:
output: nullin the finalresponse.completedevent even when output items were already streamed.parse_responseandResponse.output_textboth iterateresponse.outputdirectly →TypeError: 'NoneType' object is not iterable.text: null,parse_responsepassesNoneto the structured parser andoutput_textconcatenatesNoneinto the string.Fix
_parsing/_responses.py— iterateresponse.output or []; skip structured parsing whenitem.text is Nonetypes/responses/response.py— sameor []guard in theoutput_textproperty; skip content items wheretext is Nonelib/streaming/responses/_responses.py— whenresponse.completedarrives withoutput: null, fall back to the accumulated snapshot output instead of parsing an empty listTest
All existing tests in
tests/lib/responses/pass.