Skip to content

fix: wrap transport failures while consuming a stream - #3814

Open
lazerg wants to merge 1 commit into
openai:mainfrom
lazerg:fix/issue-3811-stream-transport-errors
Open

fix: wrap transport failures while consuming a stream#3814
lazerg wants to merge 1 commit into
openai:mainfrom
lazerg:fix/issue-3811-stream-transport-errors

Conversation

@lazerg

@lazerg lazerg commented Sep 7, 2026

Copy link
Copy Markdown
  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

_base_client wraps failures from the initial send, but Stream and AsyncStream iterate the response body with nothing around the loop. A read timeout or a dropped connection part-way through a stream therefore surfaces as a raw httpx2.ReadTimeout or httpx2.RemoteProtocolError, so except openai.APIError around a streaming call misses the most common streaming failure.

Both stream classes now catch transport failures raised while the body is consumed and re-raise them as APITimeoutError or APIConnectionError, keeping the original exception as __cause__. transport_exceptions() sits next to the existing compat helpers in _httpx2.py, so a loaded legacy httpx is covered the same way as timeout_exceptions().

Two knock-on changes come with that. The assistants event handler decides whether to fire on_timeout() from the same exception set, so APITimeoutError was added there to keep that callback firing on a stream read timeout. And test_assistant_stream_timeout_callbacks_preserve_httpx2_family asserted the raw httpx2.ReadTimeout; it now asserts the wrapper and checks __cause__, which still pins the httpx2 family.

Raw byte streaming through with_streaming_response is untouched and still surfaces httpx exceptions directly. Whether a partly consumed stream can be retried is a separate question and is not addressed here.

Additional context & links

Closes #3811

Validation:

  • 3,153 tests passed, 120 skipped, across the suite excluding tests/api_resources, tests/lib/test_fine_tuning_positional_arguments.py and tests/test_uv_workflows.py, which need the mock server or network
  • test_transport_error_mid_stream covers sync and async against both a timeout and a protocol error; all four cases fail on main
  • Ruff check and format, mypy, and Pyright passed
  • Custom-code budget: 6,626 / 10,000 lines

@lazerg
lazerg requested a review from a team as a code owner September 7, 2026 14:37

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

Copy link
Copy Markdown

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: 033cd40192

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/openai/_streaming.py
Comment on lines +112 to +113
except transport_exceptions() as err:
raise APIConnectionError(request=response.request) from err

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wrap HTTP decoding failures as connection errors

When a streaming response has malformed or truncated compressed content (for example, an invalid Content-Encoding: gzip body), response.iter_bytes() raises httpx2.DecodingError. That exception is a RequestError, not a TransportError, so this handler—and the identical async handler—still exposes a raw HTTPX2 exception instead of an APIConnectionError; consequently, except openai.APIError continues to miss this stream-consumption failure even though non-streamed responses wrap it. Catch DecodingError as well, or otherwise cover the relevant request-error family.

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.

Transport errors while consuming a stream escape as raw httpx exceptions instead of APITimeoutError / APIConnectionError

1 participant