You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Transport errors while consuming a stream escape as raw httpx exceptions instead of APITimeoutError / APIConnectionError #3811
Confirm this is an issue with the Python library and not an underlying OpenAI API
This is an issue with the Python library
Describe the bug
_base_client wraps the initial send: httpx.TimeoutException becomes APITimeoutError, other transport errors become APIConnectionError, and both go through the retry loop. Once the response is streaming, _streaming.py iterates the response with no handling at all, so a read timeout or a dropped connection mid-stream surfaces as the raw httpx.ReadTimeout / httpx.RemoteProtocolError (httpx2.* on 3.x). That is not an APIError, and max_retries is not consulted.
So except openai.APIError around a streaming call misses the most common streaming failure, and a client with max_retries=2 makes exactly one request.
Expected: the same wrapping as the initial send, APITimeoutError / APIConnectionError, so the exception hierarchy holds for the whole call. Whether a partially consumed stream can be retried is a separate question; wrapping alone fixes the catch side. anthropic-sdk-python has the same gap, same generated base: anthropics/anthropic-sdk-python#1919
To Reproduce
Run the script below. No network, the mock transport yields one chunk and then raises ReadTimeout.
The raw httpx.ReadTimeout escapes, isinstance(e, openai.APIError) is False, one request was made.
Code snippets
importplatformimportsysimportopenaitry:
importhttpx2ashttpxexceptImportError:
importhttpxFIRST=b'data: {"id":"c1","object":"chat.completion.chunk","created":0,"model":"gpt-5.2","choices":[{"index":0,"delta":{"role":"assistant","content":"hi"},"finish_reason":null}]}\n\n'requests_seen=0classDiesMidStream(httpx.SyncByteStream):
def__iter__(self):
yieldFIRSTraisehttpx.ReadTimeout("timed out while reading the stream")
defhandler(request):
globalrequests_seenrequests_seen+=1returnhttpx.Response(200, headers={"content-type": "text/event-stream"}, stream=DiesMidStream())
client=openai.OpenAI(api_key="x", http_client=httpx.Client(transport=httpx.MockTransport(handler)), max_retries=2)
print(f"python {sys.version.split()[0]}{platform.system()}, openai {openai.__version__}, httpx {httpx.__version__}")
try:
for_inclient.chat.completions.create(model="gpt-5.2", messages=[{"role": "user", "content": "hi"}], stream=True):
passexceptExceptionase: # noqa: BLE001print(f"escaped: {type(e).__module__}.{type(e).__name__}: {e}")
print(f"isinstance(e, openai.APIError) = {isinstance(e, openai.APIError)}")
print(f"requests made with max_retries=2: {requests_seen}")
Output (python 3.12.13, macOS):
openai 2.26.0, httpx 0.28.1
escaped: httpx.ReadTimeout: timed out while reading the stream
isinstance(e, openai.APIError) = False
requests made with max_retries=2: 1
openai 3.8.0, httpx 2.12.0
escaped: httpx2.ReadTimeout: timed out while reading the stream
isinstance(e, openai.APIError) = False
requests made with max_retries=2: 1
I opened #3827 with a fix for this :)
It covers sync/async mid-stream timeouts, connection errors, and decoding errors, while preserving the existing Assistants streaming behavior. The latest commit has also been re-reviewed by Codex with no major issues, and the security review is clean. Happy to adjust anything if maintainers prefer a different direction.
Thanks for reporting this! Fixed on main in #3827: stream read failures now raise APITimeoutError or APIConnectionError, preserving the original exception as __cause__. Partially consumed streams are not automatically retried.
Activity
heri-espino commentedon Sep 9, 2026
I opened #3827 with a fix for this :)
It covers sync/async mid-stream timeouts, connection errors, and decoding errors, while preserving the existing Assistants streaming behavior. The latest commit has also been re-reviewed by Codex with no major issues, and the security review is clean. Happy to adjust anything if maintainers prefer a different direction.
marcuswood-oai commentedon Sep 10, 2026
Thanks for reporting this! Fixed on main in #3827: stream read failures now raise
APITimeoutErrororAPIConnectionError, preserving the original exception as__cause__. Partially consumed streams are not automatically retried.feat(streaming): normalize errors raised while reading streams (opena…