fix(codex): handle Responses stream whose completed event has output=null - #33050
Closed
sree-sanak wants to merge 1 commit into
Closed
fix(codex): handle Responses stream whose completed event has output=null#33050sree-sanak wants to merge 1 commit into
sree-sanak wants to merge 1 commit into
Conversation
…null The chatgpt.com/backend-api/codex backend (gpt-5.x) streams the answer via response.output_item.done / response.output_text.delta events, then sends the terminal response.completed event with response.output = null. openai-python's Responses streaming accumulator calls parse_response() on that completed event, which does `for output in response.output` with no None guard (seen on openai 2.24.0, lib/_parsing/_responses.py), raising TypeError: 'NoneType' object is not iterable mid-stream. run_codex_stream only catches httpx/RuntimeError, so it propagates and fails every request against that backend. - run_codex_stream: catch the parse_response None-output TypeError and route to the existing create(stream=True) fallback, which iterates events manually and never calls parse_response. - run_codex_create_stream_fallback and the auxiliary Codex adapter: backfill output from collected stream items when the terminal output is None, not only when it is an empty list, so already-streamed content is recovered. Verified against the live backend: requests that previously crashed now return their content. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
4 tasks
Contributor
|
Closing as obsolete. PR #33042 (merged commit The symptom-patch + recovery logic this PR added on top of the SDK helper is now redundant. Thanks for the work during the outage. |
This was referenced May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The ChatGPT Codex backend (
https://chatgpt.com/backend-api/codex, gpt-5.x) streams the answer viaresponse.output_item.done/response.output_text.deltaevents, then sends the terminalresponse.completedevent withresponse.output = null.openai-python's Responses streaming accumulator calls
parse_response()on that completed event, andparse_responsedoes:with no
Noneguard (observed onopenai==2.24.0,openai/lib/_parsing/_responses.py). Whenresponse.outputisnull, this raisesTypeError: 'NoneType' object is not iterablemid-stream.run_codex_streamonly catcheshttpx/RuntimeError, so theTypeErrorpropagates and every request against that backend fails. Schedulers that wrap it re-surface it asRuntimeError: 'NoneType' object is not iterable.Fix
run_codex_stream: catch theparse_responseNone-outputTypeErrorand route to the existingcreate(stream=True)fallback, which iterates SSE events manually and never callsparse_response. This mirrors how the code already handles theresponse.created/response.completedprelude/postlude quirks for this same backend.run_codex_create_stream_fallbackand the auxiliary Codex adapter: backfilloutputfrom the collected stream items when the terminaloutputisNone(previously only handled the empty-list case), so the already-streamed content is recovered instead of lost.No behavior change for backends that send a well-formed
response.completed.Verification
Reproduced against the live backend (the streamed events arrive, the terminal
response.completedcarriesoutput: null, and the SDK raises theTypeError). With the fix, requests that previously crashed return their content normally. Both the main conversation path and the auxiliary path (title generation, etc.) recover.