Skip to content

fix(codex): recover null-output Responses turns - #33296

Closed
blackduckai wants to merge 1 commit into
NousResearch:mainfrom
blackduckai:fix/codex-null-output-and-fallback-reasoning-gate
Closed

fix(codex): recover null-output Responses turns#33296
blackduckai wants to merge 1 commit into
NousResearch:mainfrom
blackduckai:fix/codex-null-output-and-fallback-reasoning-gate

Conversation

@blackduckai

Copy link
Copy Markdown

Summary

  • recover Codex Responses turns that return null output by falling back through the existing create-stream path
  • gate encrypted reasoning replay/include behavior to reasoning-capable models
  • add Grok 4.3 context metadata and regression coverage for Codex/XAI provider parity

Test Plan

  • python -m pytest tests/run_agent/test_codex_xai_oauth_recovery.py tests/run_agent/test_provider_parity.py -v --tb=short -o 'addopts='

🤖 Generated with Hermes Agent

…easoning models

Two related failures broke the Telegram gateway (every agent turn errored,
then surfaced "model provider failed after retries"):

1. codex/gpt-5.5 null output. The chatgpt.com/backend-api/codex backend sends
   `response.completed` with `output: null` while streaming the real content
   via incremental events. The OpenAI SDK's parse_response() does
   `for output in response.output:` and raises "'NoneType' object is not
   iterable" inside the `.stream()` helper's loop. The existing backfill only
   handled an empty *list*, not None, so neither the main path nor the
   create(stream=True) fallback recovered — turns came back empty / crashed.

   - run_codex_create_stream_fallback: backfill when output is None (not just
     []), reusing the collected output_item.done items / text deltas. This is
     the path that actually recovers the text (verified live: returns the
     streamed content with a valid output list).
   - run_codex_stream: on the null-output TypeError, skip the retry (re-streaming
     reproduces the same null output deterministically) and go straight to the
     create(stream=True) fallback, which reads raw events without parse_response.
   - Both backfill sites also leave output=[] when there's nothing to recover so
     downstream `.output` iteration never re-raises.

2. gpt-4.1 fallback 400. When the codex primary fails and the chain falls back
   to a direct-OpenAI target (custom / api.openai.com) the Responses transport
   added `reasoning` + `include: ["reasoning.encrypted_content"]` for every
   model. gpt-4.1 (non-reasoning) rejects this with HTTP 400 "Encrypted content
   is not supported with this model."

   - Add model_metadata.openai_responses_supports_reasoning() (codex/gpt-5/o1/
     o3/o4 prefixes), mirroring _AZURE_FOUNDRY_RESPONSES_PREFIXES.
   - codex transport now gates reasoning/include on
     `is_codex_backend or openai_responses_supports_reasoning(model)`: the codex
     OAuth backend always gets them (contract requires reasoning replay), the
     direct OpenAI endpoint gets them only for reasoning models. gpt-4.1 / gpt-4o
     now omit them.

Tests: update the null-output fallback test to assert no wasted retry
(call_count == 1); add direct-OpenAI gpt-4.1 (omit) and gpt-5.4 (include)
gate tests. codex transport + recovery suites green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openai OpenAI / Codex Responses API codex duplicate This issue or pull request already exists labels May 27, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Late duplicate of merged #32963 (canonical Codex null-output fix). The null-output TypeError guard in run_codex_stream and run_codex_create_stream_fallback is already handled by #32963. The reasoning-gating additions in model_metadata.py are new but should be a separate PR. See also #33279 (same late duplicate pattern).

@blackduckai
blackduckai force-pushed the fix/codex-null-output-and-fallback-reasoning-gate branch from ea2ef83 to a20d2bd Compare May 27, 2026 15:26
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for this — closing as already fixed on main.

The Codex null-output crash (response.completed with output: null from the chatgpt.com backend → TypeError: 'NoneType' object is not iterable → surfaced as "non-retryable HTTP None") is resolved by commits already on main:

  • cb38ce28c — drop the SDK responses.stream() helper and consume events directly, rebuilding output from response.output_item.done events so the null terminal-event output is never iterated (refactor(codex): drop SDK responses.stream() helper; consume events directly #33042).
  • 43a3f119f — recover Codex streams with null output.
  • dc9d677d5 — classify TypeError('NoneType … not iterable') as a retryable provider-shape error so retry/fallback runs instead of killing the turn.

Your fix targets the same path that's now hardened upstream, so there's nothing left to merge here. Your authorship is preserved in your branch; I'm crediting your report in the umbrella issue #33932 (now closed). Appreciate the contribution.

@teknium1 teknium1 closed this Jun 30, 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 duplicate This issue or pull request already exists 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