Skip to content

fix(codex): handle response.completed with output=None on chatgpt.com backend#34544

Closed
ericwangzq wants to merge 1 commit into
NousResearch:mainfrom
ericwangzq:fix/codex-stream-output-none-typeerror
Closed

fix(codex): handle response.completed with output=None on chatgpt.com backend#34544
ericwangzq wants to merge 1 commit into
NousResearch:mainfrom
ericwangzq:fix/codex-stream-output-none-typeerror

Conversation

@ericwangzq

Copy link
Copy Markdown

Summary

  • The chatgpt.com/backend-api/codex endpoint sends response.completed with output=None instead of a list
  • The OpenAI SDK's parse_response() does for output in response.output: which raises TypeError: 'NoneType' object is not iterable
  • This was classified as a non-retryable local validation error, causing every request to the openai-codex provider to abort immediately

Root cause

In _run_codex_stream, the stream event loop calls self._state.handle_event(sse_event) for each event. When response.completed arrives, ResponseStreamState.accumulate_event() calls parse_response() which iterates over response.output. On the chatgpt.com backend this field is None, triggering the TypeError.

The existing except handlers only caught _httpx transport errors and RuntimeErrorTypeError propagated up to the retry loop where is_local_validation_error = isinstance(api_error, TypeError) caused immediate abort.

Fix

Catch TypeError with 'NoneType' object is not iterable in _run_codex_stream. By the time response.completed fires, all content has already arrived:

  • Output items via response.output_item.done events → collected_output_items
  • Text content via delta events → self._codex_streamed_text_parts

Build a synthetic response from that collected data and return normally, reusing the same backfill pattern already present in the function.

Test plan

  • Configure hermes with provider: openai-codex and model: gpt-5.5 pointing to https://chatgpt.com/backend-api/codex
  • Send any message — previously errored immediately with TypeError: 'NoneType' object is not iterable
  • Verify the response is received correctly after this fix

🤖 Generated with Claude Code

… backend

The chatgpt.com/backend-api/codex endpoint sends a response.completed
event with output=None instead of a list. The OpenAI SDK's parse_response()
iterates over response.output, causing:

  TypeError: 'NoneType' object is not iterable

This was classified as a non-retryable local validation error, aborting
every request to the openai-codex provider.

Fix: catch TypeError in _run_codex_stream and check for the NoneType
iteration message. By the time response.completed fires, all content
has already arrived via response.output_item.done stream events
(collected in collected_output_items) and text deltas
(_codex_streamed_text_parts). Build a synthetic response object from
that collected data and return it normally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ericwangzq

Copy link
Copy Markdown
Author

Closing — the upstream has already addressed this more thoroughly in the agent/codex_runtime.py refactor (by switching to responses.create(stream=True) and assembling the response purely from response.output_item.done events, never reading response.completed.response.output). This patch-level fix is no longer needed.

@ericwangzq ericwangzq closed this May 29, 2026
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent loop, run_agent.py, prompt builder codex labels May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex comp/agent Core agent loop, run_agent.py, prompt builder P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants