openai/openai-python · critical · WebSocketConnectionClosedError

WebSocket connection closed with unsent messages

Error message

WebSocket connection closed with unsent messages

What it means

Raised by the async WebSocket event iterator (__aiter__) when the connection closes with an error, reconnection fails, and there are still unsent messages queued for transmission. The error preserves the unsent messages so callers can recover or re-send them rather than silently dropping output.

Source

Thrown at src/openai/resources/responses/responses.py:4050

        self.response = AsyncResponsesResponseResource(self)

    async def __aiter__(self) -> AsyncIterator[ResponsesServerEvent]:
        """
        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) -> ResponsesServerEvent:
        """
        Receive the next message from the connection and parses it into a `ResponsesServerEvent` 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

  1. Catch WebSocketConnectionClosedError and re-send the unsent_messages on a fresh connection
  2. Add keep-alive/ping handling or reduce idle time to avoid mid-stream closes
  3. Implement a reconnect wrapper that re-establishes the session and replays queued output

Example fix

// before
async for event in ws:
    handle(event)
// after
try:
    async for event in ws:
        handle(event)
except WebSocketConnectionClosedError as exc:
    for msg in exc.unsent_messages:
        await outbox.put(msg)  # replay after reconnect
Defensive patterns

Strategy: try-catch

Try / catch

from openai._websocket import WebSocketConnectionClosedError
try:
    async for event in ws:
        await handle(event)
except WebSocketConnectionClosedError as exc:
    unsent = exc.unsent_messages
    ws = await reconnect()
    for msg in unsent:
        await ws.send(msg)

Prevention

When it happens

Trigger: Streaming a Responses WebSocket session, sending events while the network drops; ConnectionClosedError occurs, reconnect logic fails, and self._send_queue.drain() returns pending messages, raising WebSocketConnectionClosedError with unsent_messages attached.

Common situations: Long-running realtime/streaming sessions over unstable networks (WiFi, mobile, proxies with idle timeouts); sending bursts of input events right as the server or intermediary closes the socket.

Understand the failure class

Related errors


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/29faf78fd9181cf0. Report an issue: GitHub.