Skip to content

fix(agent): guard Codex output_text null-output access - #33428

Closed
dominicvenox wants to merge 1 commit into
NousResearch:mainfrom
dominicvenox:codex-null-output-text-guard
Closed

fix(agent): guard Codex output_text null-output access#33428
dominicvenox wants to merge 1 commit into
NousResearch:mainfrom
dominicvenox:codex-null-output-text-guard

Conversation

@dominicvenox

Copy link
Copy Markdown

Summary

Adds a defensive guard around response.output_text access in the Codex Responses normalization path.

Some SDK Response objects compute output_text by iterating response.output. If a provider returns a terminal response with output = None, that convenience property can raise:

TypeError: 'NoneType' object is not iterable

This keeps the existing empty-output recovery behavior, but avoids letting the fallback output_text check become a second crash site.

Test

python -m pytest tests/agent/test_codex_responses_adapter.py -q

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openai OpenAI / Codex Responses API codex P3 Low — cosmetic, nice to have labels May 27, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the patch and the clean test, but going to close this as effectively superseded by the wave that landed today.

What the live flow actually does when response.output is None:

  1. agent/transports/codex.py:317validate_response() returns False because response.output is not a non-empty list.
  2. agent/conversation_loop.py:1228 — the validator's caller falls into the output_text fallback branch and reads getattr(response, "output_text", None). The OpenAI SDK's output_text is a @property that iterates response.output, so that line raises TypeError: 'NoneType' object is not iterable. This is the primary crash site in production_normalize_codex_response() is downstream of it and almost never reached on the streaming path now that refactor(codex): drop SDK responses.stream() helper; consume events directly #33042 bypassed client.responses.stream() in favor of raw event iteration in agent/codex_runtime.py:run_codex_stream().
  3. The TypeError bubbles to the outer classifier in agent/conversation_loop.py:2892fix(agent): classify TypeError('NoneType ... not iterable') as retryable provider shape error #33399 added a carve-out that marks TypeError("...NoneType...not iterable...") as retryable specifically so it triggers retry+fallback instead of aborting the turn.

This PR wraps the two getattr(response, "output_text", ...) calls inside _normalize_codex_response() (lines 1004 and 1160), but doesn't touch the actual crash site at conversation_loop.py:1228. Net behavior on a live output=None frame:

  • Without this PR: TypeError → classifier carve-out → retryable → retry/fallback chain runs.
  • With this PR: TypeError still raised from conversation_loop.py:1228, classifier carve-out, retry/fallback chain runs. The only sites that change are downstream paths that almost never see output=None post-refactor(codex): drop SDK responses.stream() helper; consume events directly #33042, and there the TypeError just becomes a RuntimeError("Responses API returned no output items") that classifies identically (retryable=True, FailoverReason.unknown).

So the patch is defensive-only — doesn't fix a real failure mode and doesn't introduce one. We'd rather not add the indirection (and rename the secondary failure from TypeError to RuntimeError) for zero behavioral gain.

Background on the wave that already landed:

Empirically verified today against live chatgpt.com/backend-api/codex gpt-5.5 across 5 real workflows (single-shot + 6-turn coding session + 11-tool investigation + multi-turn replay + cross-model). Zero NoneType crashes, zero stream stalls.

Appreciate you taking the time to look at this — if you have a concrete repro where the line 1228 path still trips today, please re-open with the trace and I'll widen the fix there instead.

@teknium1 teknium1 closed this May 27, 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 runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have provider/openai OpenAI / Codex Responses API type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants