openai/openai-python · error · WebSocketConnectionClosedError
WebSocket connection closed with unsent messages
Error message
WebSocket connection closed with unsent messages
What it means
When iterating the async WebSocket response stream, the connection closed with an error and reconnection failed while messages were still queued for sending. The SDK drains the send queue and raises WebSocketConnectionClosedError with the unsent messages attached so no outbound data is silently lost. This only fires for abnormal closures (ConnectionClosedError), not clean closes.
Source
Thrown at src/openai/resources/beta/responses/responses.py:4155
self.response = AsyncResponsesResponseResource(self)
async def __aiter__(self) -> AsyncIterator[BetaResponsesServerEvent]:
"""
An infinite-iterator that will continue to yield events until
the connection is closed.
"""
from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError
while True:
try:
yield await self.recv()
except ConnectionClosedOK:
return
except ConnectionClosedError as exc:
if not await self._reconnect(exc):
unsent = self._send_queue.drain()
if unsent:
raise WebSocketConnectionClosedError(
"WebSocket connection closed with unsent messages",
unsent_messages=unsent,
) from exc
raise
async def recv(self) -> BetaResponsesServerEvent:
"""
Receive the next message from the connection and parses it into a `BetaResponsesServerEvent` object.
Canceling this method is safe. There's no risk of losing data.
"""
return self.parse_event(await self.recv_bytes())
async def recv_bytes(self) -> bytes:
"""Receive the next message from the connection as raw bytes.
Canceling this method is safe. There's no risk of losing data.
View on GitHub (pinned to 9917c6e28e)
Solutions
- Catch WebSocketConnectionClosedError and inspect .unsent_messages to know what failed to deliver; decide whether to resend on a new connection
- Check connectivity/proxy configuration if closures are frequent
- Avoid sending while the connection is closing; drain/await sends before exiting the context manager
Example fix
// before
async for event in conn:
...
// after
from openai._websocket import WebSocketConnectionClosedError
try:
async for event in conn:
...
except WebSocketConnectionClosedError as exc:
for msg in exc.unsent_messages:
await new_conn.send(msg) Defensive patterns
Strategy: try-catch
Try / catch
from openai._websocket import WebSocketConnectionClosedError
try:
async for event in conn:
handle(event)
except WebSocketConnectionClosedError as exc:
retry_with(exc.unsent_messages) Prevention
- Complete pending sends before exiting the connection context
- Monitor connection health and stop producers when the socket is down
- Wrap the iteration loop in reconnect logic for long-lived realtime sessions
When it happens
Trigger: Calling send() on the async BetaResponses WebSocket connection and then consuming with async for, when the socket drops (network failure, server-side close with error) and reconnect is disabled or fails, leaving queued sends undelivered.
Common situations: Unstable networks, proxies/load balancers with short idle timeouts, sending after the server already closed the connection, or background tasks enqueueing sends while the main task is closing the stream.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- WebSocket error: {event}
- WebSocket connection closed with unsent messages
- WebSocket connection closed with unsent messages
- max_retries cannot be None. If you want to disable retries,
- Unexpected JSON data type, {type(json_data)}, cannot merge w
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/b6db96c8c4ac6bb9.
Report an issue: GitHub.