Skip to content

Guard response parsing against null output#3381

Open
Muhtasim-Munif-Fahim wants to merge 1 commit into
openai:mainfrom
Muhtasim-Munif-Fahim:codex/openai-python-3325-null-output-guard
Open

Guard response parsing against null output#3381
Muhtasim-Munif-Fahim wants to merge 1 commit into
openai:mainfrom
Muhtasim-Munif-Fahim:codex/openai-python-3325-null-output-guard

Conversation

@Muhtasim-Munif-Fahim
Copy link
Copy Markdown

Summary

Guard parse_response() against response.output == null in response.completed payloads and add a regression test for the null-output case.

Root Cause

src/openai/lib/_parsing/_responses.py assumes response.output is always iterable:

for output in response.output:

When a backend sends response.completed with output: null, this raises TypeError during final response parsing even if earlier streamed output items were valid.

Changes

  • treat response.output as response.output or [] in parse_response()
  • add a focused unit test covering a Response object with output=None
  • keep the fix confined to non-generated parser code plus one regression test

Validation

  • python -m pytest tests/lib/responses/test_responses.py -p no:xdist -o addopts=""
  • ruff check src/openai/lib/_parsing/_responses.py tests/lib/responses/test_responses.py

Impact

This makes response parsing defensive against null output payloads while preserving existing behavior for normal responses with populated output lists.

@Muhtasim-Munif-Fahim Muhtasim-Munif-Fahim marked this pull request as ready for review June 8, 2026 02:11
@Muhtasim-Munif-Fahim Muhtasim-Munif-Fahim requested a review from a team as a code owner June 8, 2026 02:11
Copilot AI review requested due to automatic review settings June 8, 2026 02:11
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR updates response parsing to tolerate null/None response outputs and adds a regression test to ensure parsing returns an empty list in that case.

Changes:

  • Update parse_response to iterate safely when response.output is None.
  • Add a unit test asserting parse_response converts output: null into parsed.output == [].

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
tests/lib/responses/test_responses.py Adds coverage for output=None parsing behavior.
src/openai/lib/_parsing/_responses.py Makes parsing resilient to None response outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

output_list: List[ParsedResponseOutputItem[TextFormatT]] = []

for output in response.output:
for output in response.output or []:
Comment on lines +70 to +110
def test_parse_response_allows_null_output() -> None:
response = construct_type_unchecked(
type_=Response,
value={
"id": "resp_689a0b2545288193953c892439b42e2800b2e36c65a1fd4b",
"object": "response",
"created_at": 1754925861,
"status": "completed",
"background": False,
"error": None,
"incomplete_details": None,
"instructions": None,
"max_output_tokens": None,
"max_tool_calls": None,
"model": "gpt-4o-mini-2024-07-18",
"output": None,
"parallel_tool_calls": True,
"previous_response_id": None,
"prompt_cache_key": None,
"reasoning": {"effort": None, "summary": None},
"safety_identifier": None,
"service_tier": "default",
"store": True,
"temperature": 1.0,
"text": {"format": {"type": "text"}, "verbosity": "medium"},
"tool_choice": "auto",
"tools": [],
"top_logprobs": 0,
"top_p": 1.0,
"truncation": "disabled",
"usage": {
"input_tokens": 14,
"input_tokens_details": {"cached_tokens": 0},
"output_tokens": 50,
"output_tokens_details": {"reasoning_tokens": 0},
"total_tokens": 64,
},
"user": None,
"metadata": {},
},
)
@Muhtasim-Munif-Fahim Muhtasim-Munif-Fahim changed the title [codex] Guard response parsing against null output Guard response parsing against null output Jun 8, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf38cd09d5

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

output_list: List[ParsedResponseOutputItem[TextFormatT]] = []

for output in response.output:
for output in response.output or []:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve accumulated stream output when completion output is null

When a streamed response has valid response.output_item.* events but its final response.completed payload contains output: null, this fallback silently returns an empty output list. ResponseStreamState has already accumulated those items in its snapshot, but it calls parse_response() with event.response at src/openai/lib/streaming/responses/_responses.py:359-364, so the accumulated output is discarded. This avoids the prior exception but causes get_final_response() and the emitted completion event to lose all streamed content; the streaming completion path should fall back to the snapshot's output rather than converting null to an empty result.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants